import altair as alt from vega_datasets import data import geopandas as gpd df_quakes = gpd.read_file("lastday.json") df_quakes = df_quakes[df_quakes["mag"] != "-"] df_quakes["mag_num"] = df_quakes["mag"].astype(float) df_quakes = df_quakes[df_quakes.mag_num > 0] # Data generators for the background sphere = alt.sphere() graticule = alt.graticule() # Source of land data # source = alt.topo_feature(data.world_110m.url, 'countries') source = gpd.read_file("AT_and_neighbors.geojson") # Layering and configuring the components background = alt.Chart(source).mark_geoshape(fill='lightgrey', stroke='white') points = alt.Chart(df_quakes).mark_circle().encode( longitude="lon:Q", latitude="lat:Q", #size=alt.Size("mag_num:Q", title="Magnitude"), #size="magmag:Q", color="red", fillOpacity=0.5 # ).transform_calculate( # magmag="int(10*datum.mag)" ).project( type='conicConformal', center=[8, -3],
# --- Graticule Generator import altair as alt data = alt.graticule(step=[15, 15]) alt.Chart(data).mark_geoshape(stroke='black').project( 'orthographic', rotate=[0, -45, 0] ) # --- Sphere Generator import altair as alt sphere_data = alt.sphere() grat_data = alt.graticule(step=[15, 15]) background = alt.Chart(sphere_data).mark_geoshape(fill='aliceblue') lines = alt.Chart(grat_data).mark_geoshape(stroke='lightgrey') alt.layer(background, lines).project('naturalEarth1') ######## --------- # # Encodings import altair as alt from vega_datasets import data cars = data.cars()
def write(): st.header("FIFA Players Across the World") st.write("""Let's explore the distribution of footballers around the world. Hover over the map to see player stats for different countries grouped by player nationality.""") # Load in the data fifa_country_agg = load_data('data/clean_fifa_country_aggs.csv') continents_zoom_params = load_continent_zoom_params() continents = list(continents_zoom_params.keys()) # Add sliders and checkboxes for users to configure visualization player_stats_dict, player_stats_labels, player_stats_columns = load_player_stats( ) agg_functions = ['Mean', 'Min', 'Max'] # Show results for top N countries num_countries = fifa_country_agg.shape[0] st.markdown('### Show Top N Countries') top_countries_count = st.slider('N', 0, num_countries, num_countries) # Select continent to zoom into on map select_continent = st.selectbox('Continent', options=continents, index=continents.index('All')) st.subheader("Map: %s" % select_continent) # Select which player stats to show st.sidebar.markdown('### Show Player Stats') show_player_stats = st.sidebar.multiselect( 'Show in Tooltip and Table', options=player_stats_labels, default=['Age', 'Overall Rating (0-100)', 'Potential Rating (0-100)']) # Select which aggregate functions to include st.sidebar.markdown('### Show Aggregate Functions') agg_functions_checkbox = {} for a in agg_functions: agg_functions_checkbox[a] = st.sidebar.checkbox(a, value=a in ['Mean']) # Select how to determine top N countries st.sidebar.markdown('### Top N Countries Based On') top_countries_attr = st.sidebar.selectbox('Player Stat', options=player_stats_labels, index=3) top_countries_agg = st.sidebar.selectbox('Using', options=agg_functions) top_countries_order = st.sidebar.selectbox( 'Order', options=['Ascending', 'Descending'], index=1) # Draw the world map of FIFA 19 player nationalities # source: https://altair-viz.github.io/gallery/index.html#maps # Data to show based on user selections show_df = fifa_country_agg.sort_values( by='%s_%s' % (player_stats_dict.get(top_countries_attr), top_countries_agg.lower()), ascending=top_countries_order == 'Ascending').head(top_countries_count) # Data generators for the background sphere = alt.sphere() graticule = alt.graticule() # Source of land data source = alt.topo_feature(data.world_110m.url, 'countries') # Layering and configuring the components background = alt.layer( alt.Chart(sphere).mark_geoshape(fill='lightblue'), alt.Chart(graticule).mark_geoshape(stroke='white', strokeWidth=0.2), alt.Chart(source).mark_geoshape( fill='#9eb5a8', stroke='black')).project( type='equirectangular', # map type scale=continents_zoom_params.get(select_continent)[0], center=continents_zoom_params.get(select_continent) [1:3]).properties(width=800, height=400).configure_view(stroke=None) hover = alt.selection(type='single', on='mouseover', nearest=True, fields=['Latitude', 'Longitude']) # Get fields to show in tooltip tooltip_info = ['Nationality Country'] for player_stat_label in show_player_stats: player_stat_column = player_stats_dict.get(player_stat_label) for agg_function, function_checked in agg_functions_checkbox.items(): if function_checked: tooltip_info.append("%s_%s" % (player_stat_column, agg_function.lower())) base = alt.Chart(show_df).encode(longitude='Longitude:Q', latitude='Latitude:Q', tooltip=tooltip_info) points = base.mark_point().encode( color=alt.condition(~hover, alt.value('#014600'), alt.value('red')), size=alt.condition(~hover, alt.value(30), alt.value(100))).add_selection(hover) st.write(background + points) st.subheader("Data Shown on Map") st.write(show_df[tooltip_info])
def plot_all(dataset=f"data/{_OUTPUT_JSON_FILENAME}"): """ Function to plot all available maps and charts that interact. Available charts and maps: plot_stats_world plot_tweets_world plot_stats_usa plot_tweets_usa plot_choro_usa Args: dataset: JSON formatted file with tweet data. Defaults to "data/_OUTPUT_JSON_FILENAME". Returns: output_map: Collection of all maps and charts. """ try: # calling utility functions to create dataframes df_world = create_dataframe_world(dataset) df_usa = create_dataframe_us(dataset) choro = create_dataframe_choropleth(dataset) # using vega_datasets(data) countries = alt.topo_feature(data.world_110m.url, feature='countries') states = alt.topo_feature(data.us_10m.url, feature="states") # using altair function to create a spherical background sphere = alt.sphere() # setting variables for interaction # setting actual selection brush = alt.selection_multi(encodings=["y"]) # setting the opacity of (un)selected bars opacity_overview = alt.condition(brush, alt.value(0.9), alt.value(0.1)) # setting the opacity of (un)selected points opacity_points = alt.condition(brush, alt.value(1), alt.value(0)) # disable the max rows restriction to be able to chart larger datasets alt.data_transformers.disable_max_rows() # spheric background spheric_background = alt.Chart(sphere).mark_geoshape(fill="aliceblue") # us-states background background_usa = alt.Chart(states).mark_geoshape( fill="lightgray", stroke="white" ).properties( width=720, height=400 ) # world countries background background_world = alt.Chart(countries).mark_geoshape( fill='lightgray', stroke='white' ).properties( width=720, height=400 ) # plot_tweets_world() tweets_world = alt.Chart(df_world).mark_square( size=1, opacity=0.8).encode( longitude="coord_lon", latitude="coord_lat", color=alt.Color("sentiment:N", scale=alt.Scale( domain=["positive", "neutral", 'negative'], range=["green", "orange", "red"], ) ), tooltip=["user_name", "text", "sentiment"], opacity=opacity_points ).add_selection(brush).properties(title="Tweets of the world") # plot_tweets_usa() tweets_usa = alt.Chart(df_usa).mark_square(size=5, opacity=0.5).encode( longitude="coord_lon", latitude="coord_lat", color=alt.Color("sentiment:N", scale=alt.Scale( domain=["positive", "neutral", "negative"], range=["green", "orange", "red"] ) ), tooltip=["user_name", "text", "sentiment"], opacity=opacity_points ).add_selection(brush).properties(title="Tweets of the US") # plot_stats_world() stats_world = alt.Chart(df_world).mark_bar().encode( alt.Y("source_clean:N", title="sources" ), alt.X("count()"), opacity=opacity_overview, tooltip="count()" ).add_selection( brush ).properties( width=720, title="Tweet sources of the world" ).interactive() # plot_stats_usa() stats_usa = alt.Chart(df_usa).mark_bar().encode( alt.Y("source_clean:N", title="sources" ), alt.X("count()"), opacity=opacity_overview, tooltip="count()" ).add_selection( brush ).properties( width=720, title="Tweet sources of the US" ).interactive() # plot_choro_usa() choro = alt.Chart(choro).mark_geoshape().encode( color=alt.Color('sentiment', legend=alt.Legend(title="Positivity", tickCount=5, tickMinStep=0.5), scale=alt.Scale( scheme='redyellowgreen', domain=[-1, 1]) ), tooltip=["name:N", "sentiment"] ).properties( width=720, height=400, title="Average tweet sentiment per state of the US" ).add_selection(brush) # generating the final layered chart output_map = stats_world &\ (spheric_background + background_world + tweets_world).project( "naturalEarth1") &\ stats_usa &\ (background_usa + tweets_usa).project("albersUsa") &\ (background_usa + choro).project("albersUsa") return output_map except Exception: raise ValueError("""There are no tweets in the dataset yet! Try running get_data() again to collect more data or select another dataset.""")
def plot_tweets_world(dataset=f"data/{_OUTPUT_JSON_FILENAME}"): """ Function to plot all tweets worldwide as points using altair. Args: dataset: JSON formatted file with tweet data. Defaults to "data/_OUTPUT_JSON_FILENAME". Returns: output_map: map that represents the world and all tweets. Raises: ValueError: If no tweets can be found in the dataset. """ try: # calling utility function to create dataframe df = create_dataframe_world(dataset) # using vega_datasets(data) to get the borders of the countries countries = alt.topo_feature(data.world_110m.url, feature='countries') # using altair function to create a spherical background sphere = alt.sphere() # disable the max rows restriction to be able to chart large datasets alt.data_transformers.disable_max_rows() # generating chart consisting of the spherical background spheric_background = alt.Chart(sphere).mark_geoshape(fill="aliceblue") # generating chart consisting of the countries background_world = alt.Chart(countries).mark_geoshape( fill='lightgray', stroke='white' ).properties( width=720, height=400 ) # generating chart consisting of the tweets points_world = alt.Chart(df).mark_square(size=1, opacity=0.8).encode( # setting the lat/lon longitude="coord_lon", latitude="coord_lat", color=alt.Color("sentiment:N", # matching the classes onto the sentiment scale=alt.Scale(domain=[ "positive", "neutral", 'negative' ], # colouring the classes range=["green", "orange", "red"] ) ), # generating tooltip with the user name, text, sentiment of tweet tooltip=["user_name", "text", "sentiment"] ).properties(title="Tweets of the world") # generating the final layered chart output_map = (spheric_background + background_world + points_world)\ .project("naturalEarth1") return output_map except Exception: raise ValueError("""There are no tweets in the dataset yet! Try running get_data() again to collect more data or select another dataset.""")
def generate_countries_map(data: pd.DataFrame, date, interactive: bool = False, width: int = 600, height: int = 600, log_scale: bool = True) -> alt.Chart: fechas = data['fecha'].apply(lambda x: x.date()) data = data[(fechas == date)] scale = alt.Scale(type='log', scheme='teals') if log_scale else alt.Scale( type='linear', scheme='teals') url_country_name = 'https://raw.githubusercontent.com/alisle/world-110m-country-codes/master/world-110m-country-codes.json' country_names = pd.read_json(url_country_name).drop('name', axis=1) country_data = get_country_data() country_data = country_names.join((country_data.set_index('code')), on='code') data = pd.merge(left=country_data, right=data, left_on='name', right_on='pais').dropna() data = data.astype({'id': int, 'casos': int}) sphere = alt.sphere() graticule = alt.graticule() source = alt.topo_feature(vd.data.world_110m.url, 'countries') sphere_chart = alt.Chart( sphere, title='Ubicación de los casos confirmados por país').mark_geoshape( fill='lightblue') graticule_chart = alt.Chart(graticule).mark_geoshape(stroke='white', strokeWidth=0.5) countries_chart = (alt.Chart(source).mark_geoshape().encode( color=alt.Color('casos:Q', title='Casos', scale=scale, legend=None), tooltip=[ alt.Tooltip('name:N', title='País'), alt.Tooltip('code:N', title='Código'), alt.Tooltip('casos:Q', title='Casos') ]).transform_lookup('id', from_=alt.LookupData( data=data, key='id', fields=['code', 'name', 'casos']))) single = alt.selection_single( on='mouseover', nearest=True, fields=['pais'], empty='all') if interactive else alt.selection_single() circle_chart = (alt.Chart(source).mark_circle( opacity=0.4, color='red').encode( longitude='lon:Q', latitude='lat:Q', size=(alt.condition( single, alt.Size('casos:Q', scale=alt.Scale(range=[50, 4000]), legend=None), alt.value(0))), tooltip=[ alt.Tooltip('pais:N', title='País'), alt.Tooltip('code:N', title='Código'), alt.Tooltip('casos:Q', title='Casos') ]).transform_lookup('id', from_=alt.LookupData(data=data, key='id', fields=[ 'code', 'pais', 'casos', 'lat', 'lon' ])).add_selection(single)) final_chart = ((sphere_chart + graticule_chart + countries_chart + circle_chart).project('naturalEarth1').properties( width=800, height=500).configure_view(stroke=None)) return final_chart