def getIMR(data, current_year): # Create the plot #Input GeoJSON source that contains features for plotting. geosource = GeoJSONDataSource(geojson=json.dumps(data)) #Define a sequential multi-hue color palette. palette = brewer['YlGnBu'][8] #Reverse color order so that dark blue is highest value. palette = palette[::-1] #Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. Input nan_color. color_mapper = LinearColorMapper(palette=palette, low=0, high=56, nan_color='#d9d9d9') #Define custom tick labels for color bar. tick_labels = { '0': '0', '7': '7', '14': '14', '21': '21', '28': '28', '35': '35', '42': '42', '49': '49', '56': '56' } #Add hover tool hover_IMR = HoverTool( tooltips=[('Year', '@Year'), ('State/UT', '@State'), ('Infant Mortality Rate', '@IMR')]) #Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=7, width=400, height=20, border_line_color=None, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels) #Create figure object for IMR. p_IMR = figure(title='Infant Mortality Rate - ' + str(current_year), plot_height=600, plot_width=450, toolbar_location=None, tools=[hover_IMR]) p_IMR.xgrid.grid_line_color = None p_IMR.ygrid.grid_line_color = None p_IMR.axis.visible = False #Add patch renderer to figure. p_IMR.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'IMR', 'transform': color_mapper }, line_color='black', line_width=0.25, fill_alpha=1) #Specify layout p_IMR.add_layout(color_bar, 'below') curdoc().add_root(p_IMR) return (p_IMR)
def lisa_cluster(moran_loc, df, p=0.05, region_column='', title=None, plot_width=500, plot_height=500, tools=''): ''' Lisa Cluster map, coloured by local spatial autocorrelation Parameters ---------- moran_loc : esda.moran.Moran_Local instance values of Moran's Local Autocorrelation Statistic df : geopandas dataframe instance In mask_local_auto(), assign df['labels'] per row. Note that ``df`` will be modified, so calling functions uses a copy of the user provided ``df``. p : float, optional The p-value threshold for significance. Points will be colored by significance. title : str, optional Title of map. Default title=None plot_width : int, optional Width dimension of the figure in screen units/ pixels. Default = 500 plot_height : int, optional Height dimension of the figure in screen units/ pixels. Default = 500 Returns ------- fig : Bokeh figure instance Figure of LISA cluster map, colored by local spatial autocorrelation Examples -------- >>> import libpysal.api as lp >>> from libpysal import examples >>> import geopandas as gpd >>> from esda.moran import Moran_Local >>> from splot.bk import lisa_cluster >>> from bokeh.io import show >>> link = examples.get_path('columbus.shp') >>> df = gpd.read_file(link) >>> y = df['HOVAL'].values >>> w = lp.Queen.from_dataframe(df) >>> w.transform = 'r' >>> moran_loc = Moran_Local(y, w) >>> TOOLS = "tap,reset,help" >>> fig = lisa_cluster(moran_loc, df, p=0.05, tools=TOOLS) >>> show(fig) ''' # We're adding columns, do that on a copy rather than on the users' input df = df.copy() # add cluster_labels and colors5 in mask_local_auto cluster_labels, colors5, _, labels = mask_local_auto(moran_loc, p=0.05) df['labels_lisa'] = labels df['moranloc_psim'] = moran_loc.p_sim df['moranloc_q'] = moran_loc.q # load df into bokeh data source geo_source = GeoJSONDataSource(geojson=df.to_json()) fig = _lisa_cluster_fig(geo_source, moran_loc, cluster_labels, colors5, bounds=df.total_bounds, region_column=region_column, title=title, plot_width=plot_width, plot_height=plot_height, tools=tools) return fig
def build_time_evolution_tab(): # Importing geographical shapefile s3_root = 'https://covid19-bokeh-app.s3.eu-west-2.amazonaws.com' geo_data_gdf = gpd.read_file(f'{s3_root}/data/_geo_data/ne_50m_land.zip') geosource = GeoJSONDataSource(geojson=geo_data_gdf.to_json()) # Importing geo-evolutions cases/deaths data time_evol_df = pd.read_csv(f'{s3_root}/data/geo_time_evolution.csv') # Selecting earliest snapshot time_evol_df.date = pd.to_datetime(time_evol_df.date, format="%Y-%m-%d") snapshot_df = time_evol_df[time_evol_df.date == min(time_evol_df.date)] global_by_day_df = pd.read_csv(f'{s3_root}/data/global_by_day.csv') global_by_day_df.date = pd.to_datetime(global_by_day_df.date, format="%Y-%m-%d") global_totals_df = global_by_day_df.loc[global_by_day_df.date == min( time_evol_df.date)] global_cases = int(global_totals_df.iloc[0]['cases']) global_deaths = int(global_totals_df.iloc[0]['deaths']) # Applying bubble-size mapping bubble_size = snapshot_df['cases'].apply(lambda x: 0.5 * math.log(x, 1.1) if x > 0 else 0) snapshot_df = snapshot_df.assign(size=bubble_size.values) # Creating ColumnDataSource for visualisation cases_cds = ColumnDataSource(snapshot_df) # Adding figure and geographical patches from shapefile geo_plot = figure(plot_height=450, plot_width=720, x_range=(-180, 180), y_range=(-90, 90), name="time_evolution_geo_plot", sizing_mode="scale_width") geo_patches = geo_plot.patches('xs', 'ys', source=geosource, alpha=0.5) # Adding circle glyph to create bubble plot cases_circles = geo_plot.circle(x='long', y='lat', size='size', source=cases_cds, color='red', alpha=0.2) # Adding hover tool hover = HoverTool(tooltips=[('Country/Region', '@region'), ('Province/State', '@province'), ('Cases', '@cases')], renderers=[cases_circles]) geo_plot.add_tools(hover) # Adding hbar countries_df = snapshot_df.loc[:, ['date', 'region', 'cases']] countries_df.rename(columns={"cases": "value"}, inplace=True) countries_df = countries_df.groupby(['date', 'region']).sum().reset_index() countries_df.sort_values(by='value', ascending=False, inplace=True) countries_df = countries_df.reset_index(drop=True) countries_cds = ColumnDataSource(countries_df) hbar_plot = figure(plot_height=450, plot_width=475, y_range=(10.5, -0.5), x_range=(0, countries_df.value.max() * 1.2), name="time_evolution_hbar_plot", sizing_mode="scale_width") hbar = hbar_plot.hbar(left=0, right='value', y='index', source=countries_cds, height=0.5, line_color='white') labels = LabelSet(x='value', y='index', text='region', text_font_size='10pt', text_color='white', x_offset=5, y_offset=0, source=countries_cds, level='glyph', render_mode='canvas') hbar_plot.add_layout(labels) # Adding hover tool hover_hbar = HoverTool(tooltips=[('Country/Region', '@region'), ('Cases', '@value')], renderers=[hbar]) hbar_plot.add_tools(hover_hbar) # Adding callback for updating data def data_view_callback(attr, old, new): """Callback function to update data source: - Updates source data to selected data view (cases/deaths/new cases/new deaths) and selected snapshot date on date slider. - Updates HoverTool to reflect data view change - Updates Divs for total cases/deaths """ # Determine data view selection if cases_deaths_button.active == 0: data_view = "cases" elif cases_deaths_button.active == 1: data_view = "deaths" if total_new_button.active == 1: data_view = f"new_{data_view}" # Determine date selection slider_date = date_slider.value_as_datetime.date() # Filter data for selected date snapshot_df = time_evol_df[time_evol_df.date == pd.Timestamp( slider_date)] # Map bubble size on selected data view bubble_size = snapshot_df[data_view].apply( lambda x: 0.5 * math.log(x, 1.1) if x > 0 else 0) snapshot_df = snapshot_df.assign(size=bubble_size.values) cases_cds.data = snapshot_df hover.tooltips = [('Country/Region', '@region'), ('Province/State', '@province'), (data_view.replace('_', ' ').title(), f'@{data_view}')] # Update hbar data countries_df = snapshot_df.loc[:, ['date', 'region', data_view]] countries_df.rename(columns={data_view: "value"}, inplace=True) countries_df = countries_df.groupby(['date', 'region']).sum().reset_index() countries_df.sort_values(by="value", ascending=False, inplace=True) countries_df = countries_df.reset_index(drop=True) countries_cds.data = countries_df hbar_plot.x_range.end = countries_df.value.max() * 1.2 hover_hbar.tooltips = [('Country/Region', '@region'), (data_view.replace('_', ' ').title(), '@value')] # Filter for totals global_totals_df = global_by_day_df.loc[( global_by_day_df.date == pd.Timestamp(slider_date))] global_cases = int(global_totals_df.iloc[0]['cases']) global_deaths = int(global_totals_df.iloc[0]['deaths']) cases_div.text = (f'<h3 class="card-text">' f'{global_cases:,}</h3>') deaths_div.text = (f'<h3 class="card-text">' f'{global_deaths:,}</h3>') # Adding Date slider date_range = [ pd.Timestamp(date_val) for date_val in time_evol_df.date.unique() ] date_slider = DateSlider(title="Date", start=min(date_range), end=max(date_range), value=min(date_range), sizing_mode="scale_width") date_slider.on_change('value', data_view_callback) # Adding Cases/Deaths toggle cases_deaths_button = RadioButtonGroup(labels=["Cases", "Deaths"], active=0, sizing_mode="scale_width") cases_deaths_button.on_change('active', data_view_callback) # Adding Total/New toggle total_new_button = RadioButtonGroup(labels=["Total", "New"], active=0, sizing_mode="scale_width") total_new_button.on_change('active', data_view_callback) # Adding callback for zooming into a selected continent def continent_zoom_callback(attr, old, new): continent_map_ref = { # Worldwide 0: { 'x_range': [-200, 200], 'y_range': [-100, 100] }, # Europe 1: { 'x_range': [-30, 50], 'y_range': [30, 70] }, # North America 2: { 'x_range': [-175, -15], 'y_range': [0, 80] }, # South America 3: { 'x_range': [-140, 10], 'y_range': [-60, 15] }, # Africa 4: { 'x_range': [-55, 105], 'y_range': [-40, 40] }, # Asia 5: { 'x_range': [40, 140], 'y_range': [-5, 45] }, # Oceania 6: { 'x_range': [80, 200], 'y_range': [-55, 5] } } map_ref = continent_map_ref[continent_button.active] geo_plot.x_range.start = map_ref['x_range'][0] geo_plot.x_range.end = map_ref['x_range'][1] geo_plot.y_range.start = map_ref['y_range'][0] geo_plot.y_range.end = map_ref['y_range'][1] # Adding continent toggle continent_button = RadioGroup(labels=[ "Worldwide", "Europe", "North America", "South America", "Africa", "Asia", "Oceania" ], active=0) continent_button.on_change('active', continent_zoom_callback) # Adding animation with Play/Pause button callback_id = None def animate(): def animate_update(): date = date_slider.value_as_datetime.date() + timedelta(days=1) date = pd.Timestamp(date) if date >= max(date_range): date = min(date_range) date_slider.value = date global callback_id if play_button.label == '► Play': play_button.label = '❚❚ Pause' callback_id = curdoc().add_periodic_callback(animate_update, 300) else: play_button.label = '► Play' curdoc().remove_periodic_callback(callback_id) play_button = Button(label='► Play', width=60, button_type="success") play_button.on_click(animate) # Adding Cases/Deaths count cases_div = Div(text=f'<h3 class="card-text">' f'{global_cases:,}</h3>', sizing_mode="scale_width", name="cases_div") deaths_div = Div(text=f'<h3 class="card-text">' f'{global_deaths:,}</h3>', sizing_mode="scale_width", name="deaths_div") # Defining layout of tab widgets = widgetbox(date_slider, cases_deaths_button, total_new_button, play_button, continent_button, name="time_evolution_widgetbox", sizing_mode="scale_width") # Add the plot to the current document curdoc().add_root(geo_plot) curdoc().add_root(hbar_plot) curdoc().add_root(widgets) curdoc().add_root(cases_div) curdoc().add_root(deaths_div)
from bokeh.plotting import figure from bokeh.sampledata.sample_geojson import geojson as original updated = json.dumps({ 'type': 'FeatureCollection', 'features': [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-2.1208465099334717, 51.4613151550293] }, "properties": {"OrganisationCode": "Q64"} }] }) source = GeoJSONDataSource(geojson=original) p = figure(tools='box_select') p.circle(x='x', y='y', line_color=None, fill_alpha=0.8, source=source) # open a session to keep our local document in sync with server session = push_session(curdoc()) @repeat([0,1]) def update(i): # alternate between original/updated source.geojson = [original, updated][i] curdoc().add_periodic_callback(update, 100) session.show() # open the document in a browser
from bokeh.plotting import save, figure from bokeh.models import GeoJSONDataSource addresses_fp = r"C:\Users\oyeda\Desktop\AUTOGIS\AUTOGIS_PERIOD2\assignment5\data\addresses.shp" roads_fp = r"C:\Users\oyeda\Desktop\AUTOGIS\AUTOGIS_PERIOD2\assignment5\data\roads.shp" # Read the data addresses = gpd.read_file(addresses_fp) roads = gpd.read_file(roads_fp) # Reproject to the same projection CRS = roads.crs addresses = addresses.to_crs(crs=CRS) # Convert GeoDataFrames into GeoJSONDataSource objects (similar to ColumnDataSource) point_source = GeoJSONDataSource(geojson=addresses.to_json()) roads_source = GeoJSONDataSource(geojson=roads.to_json()) # Initialize our plot figure p = figure(title="A test map") # Add the lines to the map from our GeoJSONDataSource -object (it is important to specify the columns as 'xs' and 'ys') p.multi_line('xs', 'ys', source=roads_source, color='gray', line_width=3) # Add the lines to the map from our 'msource' ColumnDataSource -object p.circle('x', 'y', source=point_source, color='black', size=6) # Output filepath outfp = r"C:\Users\oyeda\Desktop\AUTOGIS\AUTOGIS_PERIOD2\assignment5\solution\test_map.html" # Save the map
# STEP 4: Merge Data Sets. gdf = pd.merge(left=gdf, right=df, left_on='ADMIN', right_on='country', how='inner') def get_geojson(year): """Input a year (int) and return corresponding GeoJSON""" gdf_year = gdf[gdf['year'] == year] return gdf_year.to_json() geosource = GeoJSONDataSource(geojson=get_geojson(2000)) # STEP 5: Plot data on a map for a single year. # 5a. Generate a blank canvas / figure. p = figure( title='Average temperature anomaly of countries over time', plot_height=600, plot_width=1000, ) palette = brewer['YlGn'][5] color_mapper = LinearColorMapper(palette=palette, low=-2.4, high=4, nan_color=palette[2])
def get_figure(year: int): ''' create bokeh figure object :param year: year :return: figure ''' df_year = df[df['year'] == year] # Merge dataframes gdf and df_2016. merged = gdf.merge(df_year, left_on='country_code', right_on='code') # Read data to json. merged_json = json.loads(merged.to_json()) # Convert to String like object. json_data = json.dumps(merged_json) # Input GeoJSON source that contains features for plotting. geosource = GeoJSONDataSource(geojson=json_data) # Define a sequential multi-hue color palette. palette = brewer['RdBu'][11] # Reverse color order so that dark blue is highest obesity. # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette=palette, low=-2, high=2) # Define custom tick labels for color bar. tick_labels = { '0': '0°C', '-0.5': '-0.5°C', '-1': '-1°C', '-1.5': '-1.5°C', '-2': '-2°C', '0.5': '0.5°C', '1': '1°C', '1.5': '1.5°C', '2': '2°C' } # Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8, width=500, height=20, border_line_color=None, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels) # Create figure object. p = figure(title='Surface temperature anomaly (degrees celcius), ' + str(year), plot_height=600, plot_width=950, toolbar_location=None) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None # Add patch renderer to figure. p.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'temperature', 'transform': color_mapper }, line_color='black', line_width=0.25, fill_alpha=1) # Specify figure layout. p.add_layout(color_bar, 'below') return p
def make_map(zipcodes_to_plot='60608', num_neighbor=3, period_str='midday', cate=[]): """ input: updated parameters selected by users output: updated visualization of nearby neighbors """ with open('chi-zip-code-tabulation-areas-2012.geojson', 'rt') as json_file: chi_json = json.load(json_file) chi_json['features'][ zipcodes[zipcodes_to_plot]]['properties']['color_type'] = 2 chi_zipcode_to_dist = pd.read_pickle('chi_zipcode_to_dist_' + period_str) # for an updated period, check the shared zip codes with geojson shared_zips = collections.defaultdict(int) for zipcode in chi_zipcode_to_dist: shared_zips[zipcode] += 1 for zipcode in zipcodes: shared_zips[zipcode] += 1 # if a zip code exists in both geojson file and hood2vec statistical file, then "YES", we can visualize it. Otherwise, "NO" for zipcode in zipcodes: if shared_zips[zipcode] == 2: chi_json['features'][ zipcodes[zipcode]]['properties']['has_data'] = 'YES' else: chi_json['features'][ zipcodes[zipcode]]['properties']['has_data'] = 'NO' # if user selects to visualize neighbors in venue type representation if cate == [0]: period_str = 'category' chi_zipcode_to_dist = pd.read_pickle('chi_zipcode_to_dist_' + period_str) # if closest zip codes are also in geojson file, we can visualize it. We set them to a lighter color "1" distances = chi_zipcode_to_dist[zipcodes_to_plot] num_neighbor_count = 0 for neighbor_idx in range(len(distances)): if shared_zips[distances[neighbor_idx][0]] == 2: num_neighbor_count += 1 chi_json['features'][zipcodes[distances[neighbor_idx] [0]]]['properties']['color_type'] = 1 if num_neighbor_count == num_neighbor: break geojson = json.dumps(chi_json) geo_source = GeoJSONDataSource(geojson=geojson) color_mapper = LinearColorMapper(palette=Viridis6) p = figure(title="Chicago", # tools=TOOLS,\ # x_axis_location=None, y_axis_location=None,\ # x_range=(-9780000, -9745000), y_range=(5130000, 5160000), x_axis_type="mercator", y_axis_type="mercator",\ ) p.axis.visible = False p.grid.grid_line_color = None # https://bokeh.pydata.org/en/latest/docs/reference/tile_providers.html # p.add_tile(get_provider(Vendors.STAMEN_TERRAIN)) # p.add_tile(CARTODBPOSITRON) p.grid.grid_line_color = None p.patches( 'xs', 'ys', fill_alpha=0.7, fill_color={ 'field': 'color_type', 'transform': color_mapper }, source=geo_source, ) # information to hover hover = HoverTool(tooltips=[('Zip Code', '@ZIP'), ('Has Data', '@has_data')]) p.add_tools(hover) # return the handler p to pass updated values to visualization return p
# For each date, extract a list of daily new cases per capita from all cantons(e.g. 'AG_diff_pc', 'AI_diff_pc', etc.), and add as a new column in merged # For instance, in the column['2020-10-31'], there are: [0.0005411327220155498, nan, nan, 0.000496300306803826, ...] list_diff_pc = case_raw.loc[:, case_raw.columns.str.contains('diff_pc')] list_diff_pc = list_diff_pc.drop(columns='CH_diff_pc') for i, d in enumerate(dates_raw): dailyNewCases = list(list_diff_pc.iloc[i]) merged[d] = dailyNewCases # Calculate circle sizes that are proportional to dnc per capita # Set the latest dnc as default merged['size'] = merged.iloc[:, -1] * 1e5 / 5 + 10 merged['dnc'] = merged.iloc[:, -2] # Build a GeoJSONDataSource from merged geosource = GeoJSONDataSource(geojson=merged.to_json()) # Task 2: Data Visualization # T2.1 Create linear color mappers for 2 attributes in demo_raw: population density, hospital beds per capita # Map their maximum values to the high, and mimimum to the low labels = ['Density', 'BedsPerCapita'] palette = bp.inferno(256)[::-1] mappers = {} mappers['Density'] = linear_cmap(field_name='Density', palette=palette, low=min(demo_raw.Density), high=max(demo_raw.Density)) mappers['BedsPerCapita'] = linear_cmap(field_name='BedsPerCapita',
#mergeset = pd.merge(puds, df_tanggal('07-04-20'), how='inner', left_on= 'name', right_on='Kelurahan') #print(mergeset[['Kecamatan','Kelurahan', 'Konfirmasi' ,'geometry']]) #mergeset.head() #mergeset.info() #print(mergeset[mergeset['is_in_muni']=='Karangpilang']) #tampilkan peta chloropleth #ubah GEOjson. #merged_json = json.loads(mergeset.to_json()) #json_data = json.dumps(merged_json) #Oper data GEOJson ke parser geosource = GeoJSONDataSource(geojson = merged_json('07-04-20')) input_field = 'Konfirmasi' hover = HoverTool(tooltips = [('Nama Kecamatan','@Kecamatan'),('Nama Kelurahan','@Kelurahan'),('Jumlah Konfirmasi Positif COVID-19','@Konfirmasi')]) p = make_plot(input_field) # Make a slider object: slider select2 = Select(title = 'Tanggal', value = '07-04-20', options=['01-04-20','02-04-20','03-04-20','04-04-20','05-04-20','06-04-20','07-04-20']) select2.on_change('value', update_plot) # Make a selection object: select select = Select(title='Pilih Kriteria:', value='Konfirmasi', options=['ODP', 'PDP','Konfirmasi']) select.on_change('value', update_plot)
advanced_plotting=True if ((enable_advancedStats) or (enable_performanceStats)) else False) plt.xaxis.major_tick_line_color = None plt.yaxis.major_tick_line_color = None plt.xaxis.minor_tick_line_color = None plt.yaxis.minor_tick_line_color = None plt.xaxis[0].ticker.num_minor_ticks = 0 plt.yaxis[0].ticker.num_minor_ticks = 0 plt.yaxis.formatter = NumeralTickFormatter(format='0,0') return plt advanced_mode = True covid19_geosource = GeoJSONDataSource(geojson=merged_json) plot_title = None #'COVID19 outbreak in India' app_title = 'COVID19 India' India_totalCases = covid19_data['total_cases'].sum() India_totalDeaths = covid19_data['deaths'].sum() print(India_totalCases) basic_covid19_plot = covid19_plot(covid19_geosource, input_df=covid19_data, input_field='total_cases', color_field='total_cases', enable_IndiaStats=True, integer_plot=True, plot_title=plot_title) basicPlot_tab = Panel(child=basic_covid19_plot, title="⌂")
def get_bounds(selectedAgegroups, selectedMeasure): df_age = df[df.AGEGROUP.isin(selectedAgegroups)].copy() df_age.Infected = df_age[selectedMeasure] df_age.Infected_plus = df_age.groupby(['OBJECTID', 'Time'], sort=False).sum().Infected.repeat( len(selectedAgegroups)).values test = df_age.Infected_plus mini = test.min() maxi = test.max() return mini, maxi #Input GeoJSON source that contains features for plotting. geosource = GeoJSONDataSource( geojson=json_data(0, ['AGE_0_18'], 'INFECTED_NOSYMPTOMS_NOTCONTAGIOUS')) a, b = get_bounds(['AGE_0_18'], 'INFECTED_NOSYMPTOMS_NOTCONTAGIOUS') #Define a color palette. palette = brewer['YlOrRd'][8] palette = palette[::-1] color_mapper = LinearColorMapper(palette=palette, low=a, high=b, nan_color='#d9d9d9') #tick_labels = {'0': '0', '5': '5', '10':'10', '20':'20', '30':'30','45':'45', '60':'60', '70': '>70'} # Initialization AGEGROUPS = df.AGEGROUP.unique() PERIODS = df.Time.unique()
d = dict(zip(cities, [{'Longitude': '', 'Latitude': ''} for c in cities])) for i in range(len(data)): if data['City'][i] in cities: d[data['City'][i]]['Type'] = data['Type'][i] d[data['City'][i]]['University'] = data['University'][i] d[data['City'][i]]['Name'] = data['Name'][i] d[data['City'][i]]['Sectors'] = data['Sectors'][i] d[data['City'][i]]['Link '] = data['Link '][i] d[data['City'][i]]['Longitude'] = longDict[data['City'][i]] d[data['City'][i]]['Latitude'] = latDict[data['City'][i]] ndf = pd.DataFrame.from_dict(d).T ndfna = ndf[ndf['Type'].notna()] world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) geosource = GeoJSONDataSource(geojson=world.to_json()) #Définir une palette #Define a sequential multi-hue color palette. palette = brewer['YlGnBu'][8] # Create figure object. p = figure(title="LEGAL HUB", plot_height=700, plot_width=1100, toolbar_location='below', tools='box_zoom, reset, undo, save, pan') p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None # On trace la carte du monde grace a notre objet geosource
def plot_map(json_data, title, mapping_field, min_value, max_value, n_colors=6, plot_height=600, plot_width=950, palette_name='RdYlBu', reverse_palette=False): """ Creates a country map to display on a notebook with a continuous variable as a color """ geosource = GeoJSONDataSource(geojson=json_data) # Define a sequential multi-hue color palette. palette = brewer[palette_name][n_colors] # Reverse color order so that dark blue is highest obesity. if reverse_palette: palette = palette[::-1] # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette=palette, low=min_value, high=max_value) # Create color bar. color_bar = ColorBar(color_mapper=color_mapper, width=500, height=20, border_line_color=None, location=(0, 0), orientation='horizontal') # Create figure object. p = figure(title=title, plot_height=plot_height, plot_width=plot_width, toolbar_location=None) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None # Add patch renderer to figure. p.patches('xs', 'ys', source=geosource, fill_color={ 'field': mapping_field, 'transform': color_mapper }, line_color='black', line_width=0.25, fill_alpha=1) # Specify figure layout. p.add_layout(color_bar, 'below') # Display figure inline in Jupyter Notebook. output_notebook() # Display figure. return p
def make_plot(df_covid_election, contiguous_usa): ''' This function makes maps of all states to show 2020 or 2016 election results and Covid data together. Users can choose to see which year's election result they want to see by clicking on the tabs provided. Args: - df_covid_election: (csv) Covid and election data in a csv file - contiguous_usa: (shp) shape data of the U.S. to make a map Returns: - plots: contains two plots and tabs on top ''' # Merge shapefile with covid data map_info = contiguous_usa.merge(df_covid_election, left_on="NAME", right_on="state") # Drop Alaska and Hawaii map_info = map_info.loc[~map_info['NAME'].isin(['Alaska', 'Hawaii'])] # Input GeoJSON source that contains features for plotting geosource = GeoJSONDataSource(geojson=map_info.to_json()) base_colors = [ "#cb181d", "#fb6a4a", "#fcae91", "#fee5d9", "#eff3ff", "#bdd7e7", "#6baed6", "#2171b5" ] # Instantiate LinearColorMapper that linearly maps numbers in a range, # into a sequence of colors. low2020 = df_covid_election["color_2020"].min() high2020 = df_covid_election["color_2020"].max() color_mapper_2020 = LinearColorMapper(palette=base_colors, low=low2020, high=high2020) low2016 = df_covid_election["color_2016"].min() high2016 = df_covid_election["color_2016"].max() color_mapper_2016 = LinearColorMapper(palette=base_colors, low=low2016, high=high2016) tick_labels_2020 = { '-8': 'Trump wins', '-6': '', '-4': '', '-2': '', '2': '', '4': '', '6': '', '8': 'Biden wins' } tick_labels_2016 = { '-8': 'Trump wins', '-6': '', '-4': '', '-2': '', '2': '', '4': '', '6': '', '8': 'Clinton wins' } # Create color bar. color_bar_2020 = ColorBar(color_mapper=color_mapper_2020, label_standoff=10, width=500, height=20, border_line_color=None, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels_2020) color_bar_2016 = ColorBar(color_mapper=color_mapper_2016, label_standoff=10, width=500, height=20, border_line_color=None, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels_2016) # Create figure object p2020 = figure(title='COVID-19 cases & 2020 election', plot_height=600, plot_width=950, toolbar_location='below', tools="pan, wheel_zoom, box_zoom, reset") p2020.xgrid.grid_line_color = None p2020.ygrid.grid_line_color = None p2016 = figure(title='COVID-19 cases & 2016 election', plot_height=600, plot_width=950, toolbar_location='below', tools="pan, wheel_zoom, box_zoom, reset") p2016.xgrid.grid_line_color = None p2016.ygrid.grid_line_color = None # Add patch renderer to figure states_2020 = p2020.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'color_2020', 'transform': color_mapper_2020 }, line_color="gray", line_width=0.25, fill_alpha=1) states_2016 = p2016.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'color_2016', 'transform': color_mapper_2016 }, line_color="gray", line_width=0.25, fill_alpha=1) # Create hover tool p2020.add_tools( HoverTool(renderers=[states_2020], tooltips=[('State', '@NAME'), ('Case Rate per 100000', '@{Case Rate per 100000}'), ('Confirmed cases', '@{Total Cases}'), ('Total deaths', '@{Total Deaths}')])) p2016.add_tools( HoverTool(renderers=[states_2016], tooltips=[('State', '@NAME'), ('Case Rate per 100000', '@{Case Rate per 100000}'), ('Confirmed cases', '@{Total Cases}'), ('Total deaths', '@{Total Deaths}')])) # Specify layout p2020.add_layout(color_bar_2020, 'below') p2016.add_layout(color_bar_2016, 'below') panel_2020 = Panel(child=p2020, title='COVID-19 cases & 2020 election') panel_2016 = Panel(child=p2016, title='COVID-19 cases & 2016 election') plots = Tabs(tabs=[panel_2020, panel_2016]) return plots
zipcodes[zipcode]]['properties']['has_data'] = 'NO' # if closest zip codes are also in geojson file, we can visualize it. We set them to a lighter color "1" distances = chi_zipcode_to_dist[zipcodes_to_plot] num_neighbor_count = 0 for neighbor_idx in range(len(distances)): if shared_zips[distances[neighbor_idx][0]] == 2: num_neighbor_count += 1 chi_json['features'][zipcodes[distances[neighbor_idx] [0]]]['properties']['color_type'] = 1 if num_neighbor_count == num_neighbor: break # convert json to string geojson = json.dumps(chi_json) geo_source = GeoJSONDataSource(geojson=geojson) # # interactive view of hood2vec. # def make_map(zipcodes_to_plot='60608', num_neighbor=3, period_str='midday', cate=[]): """ input: updated parameters selected by users output: updated visualization of nearby neighbors """ with open('chi-zip-code-tabulation-areas-2012.geojson', 'rt') as json_file: chi_json = json.load(json_file)
from atlas_db import atlas import pymongo from bokeh.io import show, output_notebook from bokeh.models import (CDSView, ColorBar, ColumnDataSource, CustomJS, CustomJSFilter, GeoJSONDataSource, HoverTool, LinearColorMapper, Slider) from bokeh.layouts import column, row, widgetbox from bokeh.palettes import brewer from bokeh.plotting import figure print("loading geojson file...") ny = gpd.read_file("bokehapp/geojson/ny.geojson") ny = ny.set_index('ZIP_CODE') ny_source = GeoJSONDataSource(geojson=ny.to_json()) print("finish loading geojson file...") # Define color palettes palette = brewer['OrRd'][8] palette = palette[:: -1] # reverse order of colors so higher values have darker colors # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette=palette, low=0, high=1) # Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8, width=500, height=20, border_line_color=None,
def geoplot( gdf_in, geometry_column="geometry", figure=None, figsize=None, title="", xlabel="Longitude", ylabel="Latitude", xlim=None, ylim=None, color="blue", colormap=None, colormap_uselog=False, colormap_range=None, category=None, dropdown=None, slider=None, slider_range=None, slider_name="", show_colorbar=True, colorbar_tick_format=None, xrange=None, yrange=None, hovertool=True, hovertool_columns=[], hovertool_string=None, simplify_shapes=None, tile_provider="CARTODBPOSITRON_RETINA", tile_provider_url=None, tile_attribution="", tile_alpha=1, panning=True, zooming=True, toolbar_location="right", show_figure=True, return_figure=True, return_html=False, legend=True, webgl=True, **kwargs, ): """Doc-String: TODO""" # Imports: import bokeh.plotting from bokeh.plotting import show from bokeh.models import ( HoverTool, LogColorMapper, LinearColorMapper, GeoJSONDataSource, WheelZoomTool, ColorBar, BasicTicker, LogTicker, Select, Slider, ColumnDataSource, ) from bokeh.models.callbacks import CustomJS from bokeh.models.widgets import Dropdown from bokeh.palettes import all_palettes from bokeh.layouts import row, column # Make a copy of the input geodataframe: gdf = gdf_in.copy() # Check layertypes: if type(gdf) != pd.DataFrame: layertypes = [] if "Point" in str(gdf.geom_type.unique()): layertypes.append("Point") if "Line" in str(gdf.geom_type.unique()): layertypes.append("Line") if "Polygon" in str(gdf.geom_type.unique()): layertypes.append("Polygon") if len(layertypes) > 1: raise Exception( f"Can only plot GeoDataFrames/Series with single type of geometry (either Point, Line or Polygon). Provided is a GeoDataFrame/Series with types: {layertypes}" ) else: layertypes = ["Point"] # Get and check provided parameters for geoplot: figure_options = { "title": title, "x_axis_label": xlabel, "y_axis_label": ylabel, "plot_width": 600, "plot_height": 400, "toolbar_location": toolbar_location, "active_scroll": "wheel_zoom", "x_axis_type": "mercator", "y_axis_type": "mercator", } if not figsize is None: width, height = figsize figure_options["plot_width"] = width figure_options["plot_height"] = height if webgl: figure_options["output_backend"] = "webgl" if type(gdf) != pd.DataFrame: # Convert GeoDataFrame to Web Mercator Projection: gdf.to_crs(epsg=3857, inplace=True) # Simplify shapes if wanted: if isinstance(simplify_shapes, numbers.Number): if layertypes[0] in ["Line", "Polygon"]: gdf[geometry_column] = gdf[geometry_column].simplify(simplify_shapes) elif not simplify_shapes is None: raise ValueError( "<simplify_shapes> parameter only accepts numbers or None." ) # Check for category, dropdown or slider (choropleth map column): category_options = 0 if not category is None: category_options += 1 category_columns = [category] if not dropdown is None: category_options += 1 category_columns = dropdown if not slider is None: category_options += 1 category_columns = slider if category_options > 1: raise ValueError( "Only one of <category>, <dropdown> or <slider> parameters is allowed to be used at once." ) # Check for category (single choropleth plot): if category is None: pass elif isinstance(category, (list, tuple)): raise ValueError( "For <category>, please provide an existing single column of the GeoDataFrame." ) elif category in gdf.columns: pass else: raise ValueError( f"Could not find column '{category}' in GeoDataFrame. For <category>, please provide an existing single column of the GeoDataFrame." ) # Check for dropdown (multiple choropleth plots via dropdown selection): if dropdown is None: pass elif not isinstance(dropdown, (list, tuple)): raise ValueError( "For <dropdown>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in dropdown: if col not in gdf.columns: raise ValueError( f"Could not find column '{col}' for <dropdown> in GeoDataFrame. " ) # Check for slider (multiple choropleth plots via slider selection): if slider is None: pass elif not isinstance(slider, (list, tuple)): raise ValueError( "For <slider>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in slider: if col not in gdf.columns: raise ValueError( f"Could not find column '{col}' for <slider> in GeoDataFrame. " ) if not slider_range is None: if not isinstance(slider_range, Iterable): raise ValueError( "<slider_range> has to be a type that is iterable like list, tuple, range, ..." ) else: slider_range = list(slider_range) if len(slider_range) != len(slider): raise ValueError( "The number of elements in <slider_range> has to be the same as in <slider>." ) steps = [] for i in range(len(slider_range) - 1): steps.append(slider_range[i + 1] - slider_range[i]) if len(set(steps)) > 1: raise ValueError( "<slider_range> has to have equal step size between each elements (like a range-object)." ) else: slider_step = steps[0] slider_start = slider_range[0] slider_end = slider_range[-1] # Check colormap if either <category>, <dropdown> or <slider> is choosen: if category_options == 1: if colormap is None: colormap = blue_colormap elif isinstance(colormap, (tuple, list)): if len(colormap) > 1: pass else: raise ValueError( f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) elif isinstance(colormap, str): if colormap in all_palettes: colormap = all_palettes[colormap] colormap = colormap[max(colormap.keys())] else: raise ValueError( f"Could not find <colormap> with name {colormap}. The following predefined colormaps are supported (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) else: raise ValueError( f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) else: if isinstance(color, str): colormap = [color] elif color is None: colormap = ["blue"] else: raise ValueError( "<color> has to be a string specifying the fill_color of the map glyph." ) # Check xlim & ylim: if xlim is not None: if isinstance(xlim, (tuple, list)): if len(xlim) == 2: xmin, xmax = xlim for _ in [xmin, xmax]: if not -180 < _ <= 180: raise ValueError( "Limits for x-axis (=Longitude) have to be between -180 and 180." ) if not xmin < xmax: raise ValueError("xmin has to be smaller than xmax.") from pyproj import Transformer transformer = Transformer.from_crs("epsg:4326", "epsg:3857") xmin = transformer.transform(0, xmin)[0] xmax = transformer.transform(0, xmax)[0] figure_options["x_range"] = (xmin, xmax) else: raise ValueError( "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180." ) else: raise ValueError( "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180." ) if ylim is not None: if isinstance(ylim, (tuple, list)): if len(ylim) == 2: ymin, ymax = ylim for _ in [ymin, ymax]: if not -90 < _ <= 90: raise ValueError( "Limits for y-axis (=Latitude) have to be between -90 and 90." ) if not ymin < ymax: raise ValueError("ymin has to be smaller than ymax.") from pyproj import Transformer transformer = Transformer.from_crs("epsg:4326", "epsg:3857") ymin = transformer.transform(ymin, 0)[1] ymax = transformer.transform(ymax, 0)[1] figure_options["y_range"] = (ymin, ymax) else: raise ValueError( "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90." ) else: raise ValueError( "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90." ) # Create Figure to draw: old_layout = None if figure is None: p = bokeh.plotting.figure(**figure_options) # Add Tile Source as Background: p = _add_backgroundtile( p, tile_provider, tile_provider_url, tile_attribution, tile_alpha ) elif isinstance(figure, type(bokeh.plotting.figure())): p = figure elif isinstance(figure, type(column())): old_layout = figure p = _get_figure(old_layout) else: raise ValueError( "Parameter <figure> has to be of type bokeh.plotting.figure or bokeh.layouts.column." ) # Get ridd of zoom on axes: for t in p.tools: if type(t) == WheelZoomTool: t.zoom_on_axis = False # Hide legend if wanted: legend_input = legend if isinstance(legend, str): pass else: legend = "GeoLayer" # Define colormapper: if len(colormap) == 1: kwargs["fill_color"] = colormap[0] elif not category is None: # Check if category column is numerical: if not issubclass(gdf[category].dtype.type, np.number): raise NotImplementedError( f"<category> plot only yet implemented for numerical columns. Column '{category}' is not numerical." ) field = category colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[field].min() colormapper_options["high"] = gdf[field].max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = str(field) elif not dropdown is None: # Check if all columns in dropdown selection are numerical: for col in dropdown: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( f"<dropdown> plot only yet implemented for numerical columns. Column '{col}' is not numerical." ) field = dropdown[0] colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[dropdown].min().min() colormapper_options["high"] = gdf[dropdown].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} legend = " " + field elif not slider is None: # Check if all columns in dropdown selection are numerical: for col in slider: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( f"<slider> plot only yet implemented for numerical columns. Column '{col}' is not numerical." ) field = slider[0] colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[slider].min().min() colormapper_options["high"] = gdf[slider].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = "Geolayer" # Check that only hovertool_columns or hovertool_string is used: if isinstance(hovertool_columns, (list, tuple, str)): if len(hovertool_columns) > 0 and hovertool_string is not None: raise ValueError( "Either <hovertool_columns> or <hovertool_string> can be used, but not both at the same time." ) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) if hovertool_string is not None: hovertool_columns = "all" # Check for Hovertool columns: if hovertool: if not isinstance(hovertool_columns, (list, tuple)): if hovertool_columns == "all": hovertool_columns = list( filter(lambda col: col != geometry_column, gdf.columns) ) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) elif len(hovertool_columns) == 0: if not category is None: hovertool_columns = [category] elif not dropdown is None: hovertool_columns = dropdown elif not slider is None: hovertool_columns = slider else: hovertool_columns = [] else: for col in hovertool_columns: if col not in gdf.columns: raise ValueError( f"Could not find columns '{col}' in GeoDataFrame. <hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) else: if category is None: hovertool_columns = [] else: hovertool_columns = [category] # Reduce DataFrame to needed columns: if type(gdf) == pd.DataFrame: gdf["Geometry"] = 0 additional_columns = ["x", "y"] else: additional_columns = [geometry_column] for kwarg, value in kwargs.items(): if isinstance(value, Hashable): if value in gdf.columns: additional_columns.append(value) if category_options == 0: gdf = gdf[list(set(hovertool_columns) | set(additional_columns))] else: gdf = gdf[ list( set(hovertool_columns) | set(category_columns) | set(additional_columns) ) ] gdf["Colormap"] = gdf[field] field = "Colormap" # Create GeoJSON DataSource for Plot: if type(gdf) != pd.DataFrame: geo_source = GeoJSONDataSource(geojson=gdf.to_json()) else: geo_source = gdf # Draw Glyph on Figure: layout = None if "Point" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] glyph = p.scatter( x="x", y="y", source=geo_source, legend_label=legend, **kwargs ) if "Line" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] del kwargs["fill_color"] glyph = p.multi_line( xs="xs", ys="ys", source=geo_source, legend_label=legend, **kwargs ) if "Polygon" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = "black" # Creates from a geoDataFrame with Polygons and Multipolygons a Pandas DataFrame # with x any y columns specifying the geometry of the Polygons: geo_source = ColumnDataSource( convert_geoDataFrame_to_patches(gdf, geometry_column) ) # Plot polygons: glyph = p.multi_polygons( xs="__x__", ys="__y__", source=geo_source, legend_label=legend, **kwargs ) # Add hovertool: if hovertool and (category_options == 1 or len(hovertool_columns) > 0): my_hover = HoverTool(renderers=[glyph]) if hovertool_string is None: my_hover.tooltips = [(str(col), "@{%s}" % col) for col in hovertool_columns] else: my_hover.tooltips = hovertool_string p.add_tools(my_hover) # Add colorbar: if show_colorbar and category_options == 1: colorbar_options = { "color_mapper": colormapper, "label_standoff": 12, "border_line_color": None, "location": (0, 0), } if colormap_uselog: colorbar_options["ticker"] = LogTicker() if colorbar_tick_format: colorbar_options["formatter"] = get_tick_formatter(colorbar_tick_format) colorbar = ColorBar(**colorbar_options) p.add_layout(colorbar, "right") # Add Dropdown Widget: if not dropdown is None: # Define Dropdown widget: dropdown_widget = Select( title="Select Choropleth Layer", options=list(zip(dropdown, dropdown)) ) # Define Callback for Dropdown widget: callback = CustomJS( args=dict( dropdown_widget=dropdown_widget, geo_source=geo_source, legend=p.legend[0].items[0], ), code=""" //Change selection of field for Colormapper for choropleth plot: geo_source.data["Colormap"] = geo_source.data[dropdown_widget.value]; geo_source.change.emit(); //Change label of Legend: legend.label["value"] = " " + dropdown_widget.value; """, ) dropdown_widget.js_on_change("value", callback) # Add Dropdown widget above the plot: if old_layout is None: layout = column(dropdown_widget, p) else: layout = column(dropdown_widget, old_layout) # Add Slider Widget: if not slider is None: if slider_range is None: slider_start = 0 slider_end = len(slider) - 1 slider_step = 1 value2name = ColumnDataSource( { "Values": np.arange( slider_start, slider_end + slider_step, slider_step ), "Names": slider, } ) # Define Slider widget: slider_widget = Slider( start=slider_start, end=slider_end, value=slider_start, step=slider_step, title=slider_name, ) # Define Callback for Slider widget: callback = CustomJS( args=dict( slider_widget=slider_widget, geo_source=geo_source, value2name=value2name, ), code=""" //Change selection of field for Colormapper for choropleth plot: var slider_value = slider_widget.value; var i; for(i=0; i<value2name.data["Names"].length; i++) { if (value2name.data["Values"][i] == slider_value) { var name = value2name.data["Names"][i]; } } geo_source.data["Colormap"] = geo_source.data[name]; geo_source.change.emit(); """, ) slider_widget.js_on_change("value", callback) # Add Slider widget above the plot: if old_layout is None: layout = column(slider_widget, p) else: layout = column(slider_widget, old_layout) # Hide legend if user wants: if legend_input is False: p.legend.visible = False # Set click policy for legend: p.legend.click_policy = "hide" # Set panning option: if panning is False: p.toolbar.active_drag = None # Set zooming option: if zooming is False: p.toolbar.active_scroll = None # Display plot and if wanted return plot: if layout is None: if old_layout is None: layout = p else: layout = old_layout # Display plot if wanted if show_figure: show(layout) # Return as (embeddable) HTML if wanted: if return_html: return embedded_html(layout) # Return plot: if return_figure: return layout
""" Hayden Le's GeoDev Technical Assessment Submission """ import pandas as pd from shapely.geometry import Point from bokeh.models import GeoJSONDataSource, LinearColorMapper, HoverTool import geopandas as gpd from bokeh.palettes import BuPu3 as palette from bokeh.plotting import figure, save # --- country borders world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) geo_source = GeoJSONDataSource(geojson=world.to_json()) # --- project locations projects = pd.read_table('locations.tsv', sep='\t') geometry = [Point(xy) for xy in zip(projects.longitude, projects.latitude)] crs = world.crs projects_df = gpd.GeoDataFrame(projects, crs=crs, geometry=geometry) project_source = GeoJSONDataSource(geojson=projects_df.to_json()) # --- create plot/figure p = figure(title="Project Locations", plot_width=800, plot_height=500, x_range=(0, 100), y_range=(30, 85), toolbar_location="below")
def geoplot(gdf_in, fig=None, figsize=None, title="", xlabel="Longitude", ylabel="Latitude", color="blue", colormap=None, colormap_uselog=False, colormap_range=None, category=None, dropdown=None, slider=None, slider_range=None, slider_name="", show_colorbar=True, xrange=None, yrange=None, hovertool=True, hovertool_columns=[], simplify_shapes=None, tile_provider="CARTODBPOSITRON_RETINA", tile_provider_url=None, tile_attribution="", tile_alpha=1, toolbar_location="right", show_figure=True, return_figure=True, return_html=False, legend=True, webgl=True, **kwargs): """Doc-String: TODO""" gdf = gdf_in.copy() # Check layertypes: layertypes = [] if "Point" in str(gdf.geom_type.unique()): layertypes.append("Point") if "Line" in str(gdf.geom_type.unique()): layertypes.append("Line") if "Polygon" in str(gdf.geom_type.unique()): layertypes.append("Polygon") if len(layertypes) > 1: raise Exception( "Can only plot GeoDataFrames/Series with single type of geometry (either Point, Line or Polygon). Provided is a GeoDataFrame/Series with types: %s" % layertypes) # Get and check provided parameters for geoplot: figure_options = { "title": title, "x_axis_label": xlabel, "y_axis_label": ylabel, "plot_width": 600, "plot_height": 400, "toolbar_location": toolbar_location, "active_scroll": "wheel_zoom", } if not figsize is None: width, height = figsize figure_options["plot_width"] = width figure_options["plot_height"] = height if webgl: figure_options["output_backend"] = "webgl" if not fig is None: raise NotImplementedError("Parameter <figure> not yet implemented.") # Convert GeoDataFrame to Web Mercador Projection: gdf.to_crs({"init": "epsg:3857"}, inplace=True) # Simplify shapes if wanted: if isinstance(simplify_shapes, numbers.Number): if layertypes[0] in ["Line", "Polygon"]: gdf["geometry"] = gdf["geometry"].simplify(simplify_shapes) elif not simplify_shapes is None: raise ValueError( "<simplify_shapes> parameter only accepts numbers or None.") # Check for category, dropdown or slider (choropleth map column): category_options = 0 if not category is None: category_options += 1 category_columns = [category] if not dropdown is None: category_options += 1 category_columns = dropdown if not slider is None: category_options += 1 category_columns = slider if category_options > 1: raise ValueError( "Only one of <category>, <dropdown> or <slider> parameters is allowed to be used at once." ) # Check for category (single choropleth plot): if category is None: pass elif isinstance(category, (list, tuple)): raise ValueError( "For <category>, please provide an existing single column of the GeoDataFrame." ) elif category in gdf.columns: pass else: raise ValueError( "Could not find column '%s' in GeoDataFrame. For <category>, please provide an existing single column of the GeoDataFrame." % category) # Check for dropdown (multiple choropleth plots via dropdown selection): if dropdown is None: pass elif not isinstance(dropdown, (list, tuple)): raise ValueError( "For <dropdown>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in dropdown: if col not in gdf.columns: raise ValueError( "Could not find column '%s' for <dropdown> in GeoDataFrame. " % col) # Check for slider (multiple choropleth plots via slider selection): if slider is None: pass elif not isinstance(slider, (list, tuple)): raise ValueError( "For <slider>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in slider: if col not in gdf.columns: raise ValueError( "Could not find column '%s' for <slider> in GeoDataFrame. " % col) if not slider_range is None: if not isinstance(slider_range, Iterable): raise ValueError( "<slider_range> has to be a type that is iterable like list, tuple, range, ..." ) else: slider_range = list(slider_range) if len(slider_range) != len(slider): raise ValueError( "The number of elements in <slider_range> has to be the same as in <slider>." ) steps = [] for i in range(len(slider_range) - 1): steps.append(slider_range[i + 1] - slider_range[i]) if len(set(steps)) > 1: raise ValueError( "<slider_range> has to have equal step size between each elements (like a range-object)." ) else: slider_step = steps[0] slider_start = slider_range[0] slider_end = slider_range[-1] # Check colormap if either <category>, <dropdown> or <slider> is choosen: if category_options == 1: if colormap is None: colormap = blue_colormap elif isinstance(colormap, (tuple, list)): if len(colormap) > 1: pass else: raise ValueError( "<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): %s" % (list(all_palettes.keys()))) elif isinstance(colormap, str): if colormap in all_palettes: colormap = all_palettes[colormap] colormap = colormap[max(colormap.keys())] else: raise ValueError( "Could not find <colormap> with name %s. The following predefined colormaps are supported (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): %s" % (colormap, list(all_palettes.keys()))) else: raise ValueError( "<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): %s" % (list(all_palettes.keys()))) else: if isinstance(color, str): colormap = [color] else: raise ValueError( "<color> has to be a string specifying the fill_color of the map glyph." ) # Create Figure to draw: p = figure(x_axis_type="mercator", y_axis_type="mercator", **figure_options) # Get ridd of zoom on axes: for t in p.tools: if type(t) == WheelZoomTool: t.zoom_on_axis = False # Add Tile Source as Background: p = _add_backgroundtile(p, tile_provider, tile_provider_url, tile_attribution, tile_alpha) # Hide legend if wanted: if not legend: p.legend.visible = False elif isinstance(legend, str): pass else: legend = "GeoLayer" # Define colormapper: if len(colormap) == 1: kwargs["fill_color"] = colormap[0] elif not category is None: # Check if category column is numerical: if not issubclass(gdf[category].dtype.type, np.number): raise NotImplementedError( "<category> plot only yet implemented for numerical columns. Column '%s' is not numerical." % category) field = category colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[field].min() colormapper_options["high"] = gdf[field].max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = str(field) elif not dropdown is None: # Check if all columns in dropdown selection are numerical: for col in dropdown: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( "<dropdown> plot only yet implemented for numerical columns. Column '%s' is not numerical." % col) field = dropdown[0] colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[dropdown].min().min() colormapper_options["high"] = gdf[dropdown].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = "Geolayer" elif not slider is None: # Check if all columns in dropdown selection are numerical: for col in slider: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( "<slider> plot only yet implemented for numerical columns. Column '%s' is not numerical." % col) field = slider[0] colormapper_options = {"palette": colormap} if not colormap_range is None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[slider].min().min() colormapper_options["high"] = gdf[slider].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = "Geolayer" # Check for Hovertool columns: if hovertool: if not isinstance(hovertool_columns, (list, tuple)): if hovertool_columns == "all": hovertool_columns = list( filter(lambda col: col != "geometry", df_shapes.columns)) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) elif len(hovertool_columns) == 0: if not category is None: hovertool_columns = [category] elif not dropdown is None: hovertool_columns = dropdown elif not slider is None: hovertool_columns = slider else: hovertool_columns = [] else: for col in hovertool_columns: if col not in gdf.columns: raise ValueError( "Could not find columns '%s' in GeoDataFrame. <hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." % col) else: if category is None: hovertool_columns = [] else: hovertool_columns = [category] # Reduce DataFrame to needed columns: additional_columns = [] for kwarg, value in kwargs.items(): if isinstance(value, Hashable): if value in gdf.columns: additional_columns.append(value) if category_options == 0: gdf = gdf[list(set(hovertool_columns) | set(additional_columns)) + ["geometry"]] else: gdf = gdf[list( set(hovertool_columns) | set(category_columns) | set(additional_columns)) + ["geometry"]] gdf["Colormap"] = gdf[field] field = "Colormap" # Create GeoJSON DataSource for Plot: geo_source = GeoJSONDataSource(geojson=gdf.to_json()) # Draw Glyph on Figure: layout = None if "Point" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] p.scatter(x="x", y="y", source=geo_source, legend=legend, **kwargs) if "Line" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] del kwargs["fill_color"] p.multi_line(xs="xs", ys="ys", source=geo_source, legend=legend, **kwargs) if "Polygon" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = "black" # Plot polygons: p.patches(xs="xs", ys="ys", source=geo_source, legend=legend, **kwargs) if hovertool and (category_options == 1 or len(hovertool_columns) > 0): my_hover = HoverTool() my_hover.tooltips = [(str(col), "@{%s}" % col) for col in hovertool_columns] p.add_tools(my_hover) if show_colorbar and category_options == 1: colorbar_options = { "color_mapper": colormapper, "label_standoff": 12, "border_line_color": None, "location": (0, 0), } if colormap_uselog: colorbar_options["ticker"] = LogTicker() colorbar = ColorBar(**colorbar_options) p.add_layout(colorbar, "right") if not dropdown is None: # Define Dropdown widget: dropdown_widget = Dropdown(label="Select Choropleth Layer", menu=list(zip(dropdown, dropdown))) # Define Callback for Dropdown widget: callback = CustomJS( args=dict(dropdown_widget=dropdown_widget, geo_source=geo_source, p=p), code=""" //Change selection of field for Colormapper for choropleth plot: geo_source.data["Colormap"] = geo_source.data[dropdown_widget.value]; geo_source.change.emit(); //p.legend[0].items[0]["label"] = dropdown_widget.value; """, ) dropdown_widget.js_on_change("value", callback) # Add Dropdown widget above the plot: layout = column(dropdown_widget, p) if not slider is None: if slider_range is None: slider_start = 0 slider_end = len(slider) - 1 slider_step = 1 value2name = ColumnDataSource({ "Values": np.arange(slider_start, slider_end + slider_step, slider_step), "Names": slider, }) # Define Slider widget: slider_widget = Slider( start=slider_start, end=slider_end, value=slider_start, step=slider_step, title=slider_name, ) # Define Callback for Slider widget: callback = CustomJS( args=dict( slider_widget=slider_widget, geo_source=geo_source, value2name=value2name, ), code=""" //Change selection of field for Colormapper for choropleth plot: var slider_value = slider_widget.value; for(i=0; i<value2name.data["Names"].length; i++) { if (value2name.data["Values"][i] == slider_value) { var name = value2name.data["Names"][i]; } } geo_source.data["Colormap"] = geo_source.data[name]; geo_source.change.emit(); """, ) slider_widget.js_on_change("value", callback) # Add Slider widget above the plot: layout = column(slider_widget, p) # Set click policy for legend: p.legend.click_policy = "hide" # Display plot and if wanted return plot: if layout is None: layout = p # Display plot if wanted if show_figure: show(layout) # Return as (embeddable) HTML if wanted: if return_html: return embedded_html(layout) # Return plot: if return_figure: return layout
def get_geodatasource(pop_states): """Get getjsondatasource from geopandas object""" json_data = json.dumps(json.loads(pop_states.to_json())) return GeoJSONDataSource(geojson=json_data)
] normalizedTotalCases() normalizedTotalDeaths() normalizedTotalCasesPerMillion() normalizedTotalDeathsPerMillion() geoDataFrame = geoDataFrame.merge(covidDataFrame, left_on='country_code', right_on='iso_code', how='left') # convert date column to string as datetime dtype cannot be converted as JSON geoDataFrame['date'] = geoDataFrame['date'].astype(str) jsonGeoData = json.loads(geoDataFrame.to_json()) source = GeoJSONDataSource(geojson=json.dumps(jsonGeoData)) # sequential multi-hue color palette. palette = brewer['YlGnBu'][8] # reverse color order so that dark blue is highest obesity. palette = palette[::-1] color_mapper = LinearColorMapper(palette=palette, low=0, high=8) # define custom tick labels for color bar. # tick_labels = {'0': '0%', '5': '5%', '10': '10%', '15': '15%', # '20': '20%', '25': '25%', '30': '30%', '35': '35%', '40': '>40%'} # Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8, width=500, height=20, border_line_color=None,
def get_plot(query, conn, desc, first, last): # Get one of the results tables df = gpd.GeoDataFrame.from_postgis(query, conn, geom_col='geom', crs=from_epsg(3067)).to_crs("EPSG:3857") # A point source for labels. df.set_geometry() fails, but this works! df_centroids = gpd.GeoDataFrame.from_postgis( query, conn, geom_col='geom_centroid', crs=from_epsg(3067)).to_crs("EPSG:3857") # Classify data (manual classes based on outputs of previous runs!) breaks = [-10.1, 10, 101] classifier = mc.UserDefined.make(bins=breaks) classes = df[['RFChange']].apply(classifier) classes.columns = ['Class'] df = df.join(classes) # Collect some statistics: # For practical help how to do this in Python: # https://pythonfordatascience.org/independent-t-test-python/ statistics = { 'min_rfchg': df['RFChange'].min(), 'max_rfchg': df['RFChange'].max(), 'min_abschg': df['AbsChange'].min(), 'max_abschg': df['AbsChange'].max(), 'mean_rfchg': df['RFChange'].mean(), 'mean_abschg': df['AbsChange'].mean(), 'median_abschg': df['AbsChange'].median(), 'stdev_abschg': df['AbsChange'].std(), 'mean_T1': df['T1'].mean(), 'mean_T2': df['T2'].mean(), 'stdev_T1': df['T1'].std(), 'stdev_T2': df['T2'].std(), 'levenestat_abschg': None, 'levenepval_abschg': None, 'shapirostat_abschg': None, 'shapiropval_abschg': None, 't-stat_abschg': None, 't-pval_abschg': None, 't-df_abschg': None } # None of this makes sense unless both variables have data: reshist = None resqq = None if not ((df['T1'] == 0).all() or (df['T2'] == 0).all()): # Null hypothesis for Levene test: both inputs have equal variances. statistics['levenestat_abschg'], \ statistics['levenepval_abschg'] = stats.levene(df['T1'], df['T2']) # Null hypothesis for Shapiro-Wilk: normal distribution of residuals. diff = df['T2'] - df['T1'] statistics['shapirostat_abschg'], \ statistics['shapiropval_abschg'] = stats.shapiro(diff) plot_title = 'Residuals for ' + desc + ', ' + first + '–' + last reshist = diff.plot(kind='hist', title="\n".join(wrap(plot_title, 60)), figure=plt.figure()) plt.figure() stats.probplot(diff, plot=plt) plt.title("\n".join(wrap(plot_title, 60))) resqq = plt.gca() statistics['t-stat_abschg'], \ statistics['t-pval_abschg'] = stats.ttest_ind(df['T1'], df['T2']) statistics['t-df_abschg'] = df['T1'].count() + df['T2'].count() - 2 # Do not use researchpy; it outputs a dataframe, and digging results # out of that just adds complexity. # statistics['descriptives_abs'], statistics['ttest_abs'] = rp.ttest( # df['T1'], df['T2']) # Define class names cnames = ['[-100…-10[', '[-10…10]', ']10…100]'] # Adding labels doesn't make sense as legend plotting does not work # (see below). # for i in range(len(cnames)): # df['Label'] = None # df.loc[df['Class'] == i, 'Label'] = cnames[i] # Get the tile provider. Ideally I should define my own and use # an NLS bkg map, but defining an own WTMS source is painstaking! tiles = get_provider(Vendors.CARTODBPOSITRON_RETINA) # tiles = get_provider(Vendors.STAMEN_TERRAIN_RETINA) # Try to plot a map plot = figure( x_range=(2725000, 2815000), y_range=(8455000, 8457000), # x_range=(2725000,2815000), # y_range=(8355000,8457000), x_axis_type="mercator", y_axis_type="mercator", height=450, width=600, title=desc + ', ' + first + '–' + last) plot.add_tile(tiles, level='underlay') # Create the colour mapper colourmapper = LinearColorMapper(low=1, high=1, palette=[palettes.RdYlBu[9][4]], low_color=palettes.RdYlBu[9][0], high_color=palettes.RdYlBu[9][8]) # Create a map source from the DB results table and plot it mapsource = GeoJSONDataSource(geojson=df.to_json()) plot.patches('xs', 'ys', fill_color={ 'field': 'Class', 'transform': colourmapper }, line_color='gray', source=mapsource, line_width=1, level='underlay') # Plot labels from centroids labsource = GeoJSONDataSource(geojson=df_centroids.to_json()) # DEBUG: mark centroids on maps # plot.circle('x', 'y', source=labsource, color='red', size=10, level='underlay') labels = LabelSet(x='x', y='y', text='RFChange', text_font_size='8pt', x_offset=-4, y_offset=-7, source=labsource, level='glyph') plot.add_layout(labels) # Cite map sources citation = Label( x=3, y=0, x_units='screen', y_units='screen', text='Map data: Statistics Finland, UH / Accessibility Research Group', render_mode='css', text_font_size='7.25pt', text_color='black', border_line_color='white', border_line_alpha=0.1, border_line_width=1.0, background_fill_color='white', background_fill_alpha=0.4) plot.add_layout(citation) bkg_map_head = Label(x=298, y=0, x_units='screen', y_units='screen', text='Background map: ', render_mode='css', text_font_size='7.25pt', text_color='black', border_line_color='white', border_line_alpha=0.1, border_line_width=1.0, background_fill_color='white', background_fill_alpha=0.4) plot.add_layout(bkg_map_head) # Create a legend. Of course it does NOT work automatically, see # https://github.com/bokeh/bokeh/issues/9398, but MUST still be defined # by data. :( # The easiest way is to create fake elements and position them so that # they're invisible, but draw a legend for them anyway. xq = list() yq = list() for i in range(3): xq.append(2800000 + 1000 * i) for i in range(3): xq.append(8500000 + 1000 * i) colours = [ palettes.RdYlBu[9][0], palettes.RdYlBu[9][4], palettes.RdYlBu[9][8] ] legend_renderer = plot.multi_line([xq, xq, xq], [yq, yq, yq], color=colours, line_width=20) legend = [ LegendItem(label=cnames[0], renderers=[legend_renderer], index=0), LegendItem(label=cnames[1], renderers=[legend_renderer], index=1), LegendItem(label=cnames[2], renderers=[legend_renderer], index=2) ] plot.add_layout( Legend(items=legend, location='top_right', title='Change, %-p.')) hoverinfo = HoverTool() hoverinfo.tooltips = [('Region', '@nimi'), ('Mean time ' + first, '@T1'), ('Mean time ' + last, '@T2'), ('Mean time change', '@AbsChange'), ('Change, %-point of the industry total', '@RFChange')] plot.add_tools(hoverinfo) return plot, statistics, reshist, resqq
def visualization(): # Read sqlite query results into a pandas DataFrame index db1 = sqlite3.connect("SQL_data/index.sqlite") df1 = pd.read_sql_query("SELECT * from Trails", db1) db1.close() # Set renderer for plotting sqlsource = ColumnDataSource(df1) # print(sqlsource) # Read in shapefile and examine data contiguous_usa = gpd.read_file('Data/cb_2018_us_state_20m.shp') # print(contiguous_usa.head()) # Read in state population data and examine read_file = pd.read_excel('Data/US_State_Elev_Peaks_name.xlsx') read_file.to_csv('Data/US_STATE_EP.csv', index=None, header=True) state_elav = pd.read_csv('Data/US_STATE_EP.csv') # print(state_elav.head()) # Merge shapefile with Highest Peaks data elav_states = contiguous_usa.merge(state_elav, left_on=["NAME"], right_on=["NAME"]) # Drop Alaska and Hawaii elav_states = elav_states.loc[~elav_states['NAME']. isin(['Alaska', 'Hawaii'])] geosource = GeoJSONDataSource(geojson=elav_states.to_json()) # Create figure object. p = figure(title='Hiking Trails Mapping', plot_height=600, plot_width=950, toolbar_location='right', tools="pan,wheel_zoom,box_zoom,reset", active_scroll="wheel_zoom") p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None # Add patch renderer to figure. states = p.patches('xs', 'ys', source=geosource, fill_color=None, line_color="gray", line_width=0.25, fill_alpha=1) # Define color palettes palette = brewer['BrBG'][11] # palette = mpl['Cividis'][10] # ('#440154', '#30678D', '#35B778', '#FDE724') palette = palette[:: -1] # reverse order of colors so higher values have darker colors # Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette=palette, low=0, high=15000) # Define custom tick labels for color bar. tick_labels = { "0": "0", "500": "500", "1000": "1,000", "1500": "1,500", "2500": "2,500", "3500": '3,500', "4000": "4,000", "7,000": "7,000", "10000": "10,000", "14,000": "14,000", "18000": "18,000", "22000": "22,000+" } # Create color bar. color_bar = ColorBar(color_mapper=color_mapper, label_standoff=10, width=500, height=20, border_line_color=None, scale_alpha=0.5, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels) # Create figure object. p = figure( title= 'Hiking Trail Locations and Highest State Elevation Peak Data (US mainland)', plot_height=600, plot_width=950, toolbar_location='right', tools="pan, wheel_zoom, box_zoom, reset, tap") p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.title.text_font_size = "6px" p.toolbar.active_scroll = p.select_one(WheelZoomTool) # Add patch renderer to figure. states = p.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'H_Elevation', 'transform': color_mapper }, line_color='gray', line_width=0.25, fill_alpha=0.5) trails = p.circle('longitude', 'latitude', radius=0.01, source=sqlsource, color="black") # Create Tap tool taptool = p.select(type=TapTool) # url = df[url] taptool.callback = OpenURL(url='@url') # Create hover tool (trail location circles) p.add_tools( HoverTool(renderers=[trails], tooltips=[('Trail', '@name'), ('Length', '@length'), ('Latitude', '@latitude'), ('Longitude', '@longitude'), ("Stars", "@stars"), ("URL", '@url')])) # Create hover tool (States and Highest Elevation) p.add_tools( HoverTool(renderers=[states], tooltips=[('State', '@NAME'), ('Highest Elevation', '@H_Elevation')])) p.add_tools # Add the Legend Color Bar p.add_layout(color_bar, 'below') # add text info to layout p.title.text_font_size = "20px" p.add_layout(Title(text="Legend: Altitude(feet)", align="left"), "below") p.add_layout(Title(text="Click on Trail for url", align="left"), "above") # return to ___main___ return show(p)
return '7' elif x==45: return '8' elif x==83: return '9' elif x==184: return '10' else: return '0' NY_zip_count['color1']=NY_zip_count['nb_count'].map(rank_to) values = {'neighbourhood_group': 'N/A', 'nb_count': 'N/A'} NY_zip_count=NY_zip_count.fillna(value=values) NY_zip_count geosource1 = GeoJSONDataSource(geojson = NY_zip_count.to_json()) # Define color palettes palette =['#300711', '#580C1F', '#CC0000','#9C0D38', '#FF5A5F', '#F26F80', '#CC8B86', '#F9B5AC', '#FAC9C2', '#FCE6EC', '#E0E0E0'] # reverse order of colors so higher values have darker colors palette = palette[::-1] # Instantiate Categorical ColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette = palette,low=0,high=10) def map2(): #Create figure object p2 = figure(title = 'Hotels in Manhattan', plot_height = 750 ,
try: return float(cities[cities['Ville'] == x]['Latitude']) except TypeError: return None def find_long(x): try: return float(cities[cities['Ville'] == x]['Longitude']) except TypeError: return None summary = df[['Positif', 'Ville']].groupby("Ville").sum().reset_index() summary['latitude'] = summary['Ville'].apply(lambda x: find_lat(x)) summary['longitude'] = summary['Ville'].apply(lambda x: find_long(x)) geosource = GeoJSONDataSource(geojson=grid) pointsource = ColumnDataSource(summary) hover = HoverTool( tooltips=[('Ville', '@Ville'), ('Nombre de cas positifs (au moins)', '@Positif')]) #Create figure object. p = figure(plot_height=550, plot_width=700, tools=[hover, 'pan', 'wheel_zoom']) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.xaxis.visible = False p.yaxis.visible = False
def map_tab(map_all_data, score_types_list, sources_list): # Filter data we start with score_type_filter = 'InSample' #'OOS' source_filter = 'Best' geosource = GeoJSONDataSource(geojson = \ map_all_data[score_type_filter + '|' + source_filter].geojson) ## Map formatting ################## palette = Viridis256 # brewer["Spectral"][8] # Category20[20] # brewer["PRGn"][11] color_mapper = LinearColorMapper(palette=palette, low=-1, high=1) color_bar = ColorBar(color_mapper=color_mapper, width=650, height=20, formatter=NumeralTickFormatter(format=",0.00"), border_line_color=None, orientation='horizontal', location=(0, 0)) hover = HoverTool(tooltips=[('Region', '@Region'), ('Value', '@Value')]) #Create figure object. width = 750 height = np.int(width * 13 / 15) p = figure(title='Venezuela Situational Awareness', plot_height=height, plot_width=width, tools=[hover, "pan,wheel_zoom,box_zoom,reset"], toolbar_location="left") p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None #Add patch renderer to figure. p.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'Value', 'transform': color_mapper }, line_color='white', line_width=1, fill_alpha=0.7) #Specify figure layout. p.add_layout(color_bar, 'below') ## Radio buttons # Define buttons score_types = score_types_list.tolist() score_type_button = RadioButtonGroup(labels=score_types, active=0) data_sources = sources_list.tolist() sources_button = RadioButtonGroup(labels=data_sources, active=0) # Update function def score_type_callback(attr, old, new): # Get new selected value #new_score = score_types[new.active] new_score = score_types[score_type_button.active] new_source = data_sources[sources_button.active] new_key = new_score + '|' + new_source geosource_new = map_all_data[new_key] geosource.geojson = geosource_new.geojson # Update events score_type_button.on_change('active', score_type_callback) sources_button.on_change('active', score_type_callback) # Figure formatting set_stype(p) # Put controls in a single element controls = WidgetBox(score_type_button, sources_button) # Create a row layout layout = column(controls, p) # Make a tab with the layout tab = Panel(child=layout, title='Map of Scores') return tab
merged = gdf.merge(df_2016, left_on='country_code', right_on='code', how='left') #Replace NaN values to string 'No data'. merged.fillna('No data', inplace=True) #Read data to json merged_json = json.loads(merged.to_json()) #Convert to str like object json_data = json.dumps(merged_json) #Input GeoJSON source that contains features for plotting. geosource = GeoJSONDataSource(geojson=json_data) #Define a sequential multi-hue color palette. palette = brewer['YlGnBu'][8] #Reverse color order so that dark blue is highest obesity. palette = palette[::-1] #Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. color_mapper = LinearColorMapper(palette=palette, low=0, high=40) #Define custom tick labels for color bar. tick_labels = { '0': '0%', '5': '5%', '10': '10%',
df1_yr = df1[df1['yr'] == yr] df2_yr = df2[df2['yr'] == yr] merged1 = gdf.merge(df1_yr, left_index=True, right_on='LGA', how='left') merged1.fillna({'beta_ndifgdp': 'No data'}, inplace=True) merged2 = gdf.merge(df2_yr, left_index=True, right_on='LGA', how='left') merged2.fillna({'beta_ndifpop': 'No data'}, inplace=True) merged_json1 = json.loads(merged1.to_json()) json_data1 = json.dumps(merged_json1) merged_json2 = json.loads(merged2.to_json()) json_data2 = json.dumps(merged_json2) return json_data1, json_data2 #Input GeoJSON source that contains features for plotting. json1, json2 = json_data(2001) geosource1 = GeoJSONDataSource(geojson=json1) geosource2 = GeoJSONDataSource(geojson=json2) #Define a sequential multi-hue color palette. palette = brewer['YlGnBu'][8] #Reverse color order so that dark blue is highest coefficient. palette = palette[::-1] #Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. Input nan_color. color_mapper1 = LinearColorMapper(palette=palette, low=0, high=10, nan_color='#d9d9d9') color_mapper2 = LinearColorMapper(palette=palette, low=-0.3, high=0.5, nan_color='#d9d9d9') #Add hover tool
# The plot server must be running (`bokeh serve`) then run this script to push to it import time import json from bokeh.client import push_session from bokeh.io import curdoc from bokeh.models import GeoJSONDataSource from bokeh.plotting import figure from bokeh.sampledata.sample_geojson import geojson as original p = figure(tools='box_select') source = GeoJSONDataSource(geojson=original) p.circle(line_color=None, fill_alpha=0.8, source=source) # Open a session which will keep our local doc in sync with server session = push_session(curdoc()) # Open the session in a browser session.show() is_original = True while True: if is_original: # update to something else source.geojson = json.dumps( {'type': 'FeatureCollection', 'features': [ {"type": "Feature", "geometry": {"type": "Point",
'field': ward_name, 'transform': color_mapper }, line_color='black', line_width=0.25, fill_alpha=1) # Specify color bar layout. p.add_layout(color_bar, 'below') # Add the hover tool to the graph p.add_tools(hover) return p geosource = GeoJSONDataSource(geojson=json_data('2019-06-01')) # Input geojson source that contains features for plotting for: # initial year 2018 and initial criteria sale_price_median ward_name = 'total' all_wards_names = [ 'total', 'mental_health', 'maternity', 'learning_dis', 'general_acute' ] # Define a sequential multi-hue color palette. palette = brewer['Blues'][8] # Reverse color order so that dark blue is highest obesity. palette = palette[::-1] # Add hover tool