I'm trying to add a slider to filter the cities that show up on a map of the world. When i just add all cities with the code below it works fine.
import pandas as pd
import numpy as np
import geopandas
import geoplot
import json
from bokeh.io import output_notebook, show, output_file
from bokeh.models import (NumeralTickFormatter, Select, CDSView, ColorBar, ColumnDataSource,
CustomJS, CustomJSFilter,
GeoJSONDataSource, HoverTool,
LinearColorMapper, Slider)
from bokeh.io.doc import curdoc
from bokeh.layouts import column, row, widgetbox
from bokeh.palettes import brewer
from bokeh.plotting import figure, Figure
world = geopandas.read_file(
geopandas.datasets.get_path('naturalearth_lowres')
)
bokeh_ready = json.dumps(json.loads(world.to_json()))
geosource = GeoJSONDataSource(geojson = world.to_json())
cities = pd.read_csv('/Users/620751/Documents/cities.csv')
geocities = GeoJSONDataSource(geojson = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm','Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry']].to_json())
cities_input = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm', 'Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry', 'duration_hours']]
p1 = Figure(title = 'Flights',
plot_height = 720 ,
plot_width = 1200,
toolbar_location = 'below',
tools = 'pan, wheel_zoom, box_zoom, reset')
p1.xgrid.grid_line_color = None
p1.ygrid.grid_line_color = None# Add patch renderer to figure.
countries = p1.patches('xs','ys', source = geosource,
fill_color = None,
line_color = 'gray',
line_width = 0.25,
fill_alpha = 1)# Create hover tool
p1.add_tools(HoverTool(renderers = [countries],
tooltips = [('Country','@name')]))
cities_input = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm','Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry','duration_hours']]
city_source = ColumnDataSource(cities.drop('geometry', axis=1))
city_pt = p1.circle('dest_long', 'dest_lat', source = newsource,
color='red')
p1.add_tools(HoverTool(renderers = [newsource],line_policy='next',
tooltips = [('City','@MAILG_CTY_NM'),
('Departure Time','@Leg_Dep_Dt_Tm'),
('Seats','@seats'),
('Flight Time','@duration_hours' + ' hours'),
('weather', '@weather_desc' + ' low:' + '@low_temp' + ' high:' + '@high_temp' + ' rain:' + '@rain')]))
layout = column(p1)
curdoc().add_root(layout)
When I try to add a slider so I can filter what cities show on the map(based on flight time from base city using column 'duration_hours' I tried to change my code to this:
import pandas as pd
import numpy as np
import geopandas
import geoplot
import json
from bokeh.io import output_notebook, show, output_file
from bokeh.models import (NumeralTickFormatter, Select, CDSView, ColorBar, ColumnDataSource,
CustomJS, CustomJSFilter,
GeoJSONDataSource, HoverTool,
LinearColorMapper, Slider)
from bokeh.io.doc import curdoc
from bokeh.layouts import column, row, widgetbox
from bokeh.palettes import brewer
from bokeh.plotting import figure, Figure
world = geopandas.read_file(
geopandas.datasets.get_path('naturalearth_lowres')
)
bokeh_ready = json.dumps(json.loads(world.to_json()))
geosource = GeoJSONDataSource(geojson = world.to_json())
cities = pd.read_csv('/Users/620751/Documents/cities.csv')
#cities = geopandas.GeoDataFrame(lat_long1, geometry=geopandas.points_from_xy(lat_long.dest_long, lat_long.dest_lat))
cities['Leg_Arrv_Dt_Tm'] = [str(a) for a in cities['Leg_Arrv_Dt_Tm']]
cities['Leg_Dep_Dt_Tm'] = [str(a) for a in cities['Leg_Dep_Dt_Tm']]
cities['Leg_Dep_Dt'] = [str(a) for a in cities['Leg_Dep_Dt']]
cities.Leg_Dep_Tm = [str(a) for a in cities['Leg_Dep_Tm']]
geocities = GeoJSONDataSource(geojson = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm','Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry']].to_json())
cities_input = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm', 'Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry', 'duration_hours']]
p1 = Figure(title = 'Flights',
plot_height = 720 ,
plot_width = 1200,
toolbar_location = 'below',
tools = 'pan, wheel_zoom, box_zoom, reset')
p1.xgrid.grid_line_color = None
p1.ygrid.grid_line_color = None# Add patch renderer to figure.
countries = p1.patches('xs','ys', source = geosource,
fill_color = None,
line_color = 'gray',
line_width = 0.25,
fill_alpha = 1)# Create hover tool
p1.add_tools(HoverTool(renderers = [countries],
tooltips = [('Country','@name')]))
cities_input = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm','Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry','duration_hours']]
def json_data(duration):
dur = duration
df_dur = cities_input[cities_input['duration_hours'] <= dur]
dur_json = json.loads(df_dur.to_json())
json_data = json.dumps(dur_json)
return json_data
newsource = GeoJSONDataSource(geojson = json_data(24))
def update_plot(attr, old, new):
yr = slider.value
new_data = json_data(yr)
newsource.geojson = new_data
slider = Slider(title='Duration', start=0, end = int(np.round(cities.duration_hours.max(),0)), step=1, value=12)
city_pt = p1.circle('dest_long', 'dest_lat', source = newsource,
color='red')
p1.add_tools(HoverTool(renderers = [newsource],line_policy='next',
tooltips = [('City','@MAILG_CTY_NM'),
('Departure Time','@Leg_Dep_Dt_Tm'),
('Seats','@seats'),
('Flight Time','@duration_hours' + ' hours'),
('weather', '@weather_desc' + ' low:' + '@low_temp' + ' high:' + '@high_temp' + ' rain:' + '@rain')]))
slider.on_change('value', update_plot)
layout = column(p1,widgetbox(slider))
curdoc().add_root(layout)
Instead of a map with all the cities shown as red dots I get a blank screen. I'm not sure what dumb mistake I am making but I hope someone might?
Welp, I had to rewrite a bit of it but I got it working correctly. Credit to towardsdatascience where I stole the code template from.
import pandas as pd
import numpy as np
import geopandas
import geoplot
import json
from bokeh.io import output_notebook, show, output_file
from bokeh.models import (NumeralTickFormatter, Select, CDSView, ColorBar, ColumnDataSource,
CustomJS, CustomJSFilter,
GeoJSONDataSource, HoverTool,
LinearColorMapper, Slider)
from bokeh.io.doc import curdoc
from bokeh.layouts import column, row, widgetbox
from bokeh.palettes import brewer
from bokeh.plotting import figure, Figure
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn
world = geopandas.read_file(
geopandas.datasets.get_path('naturalearth_lowres')
)
bokeh_ready = json.dumps(json.loads(world.to_json()))
geosource = GeoJSONDataSource(geojson = world.to_json())
cities = pd.read_csv('/Users/620751/Documents/cities.csv')
#cities = geopandas.GeoDataFrame(lat_long1, geometry=geopandas.points_from_xy(lat_long.dest_long, lat_long.dest_lat))
cities['Leg_Arrv_Dt_Tm'] = [str(a) for a in cities['Leg_Arrv_Dt_Tm']]
cities['Leg_Dep_Dt_Tm'] = [str(a) for a in cities['Leg_Dep_Dt_Tm']]
cities['Leg_Dep_Dt'] = [str(a) for a in cities['Leg_Dep_Dt']]
cities.Leg_Dep_Tm = [str(a) for a in cities['Leg_Dep_Tm']]
geocities = GeoJSONDataSource(geojson = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm','Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry']].to_json())
cities_input = cities[['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'MAILG_ST_CTRY_NM',
'Leg_Dep_Dt', 'Opr_Car_Flt_Nbr', 'Leg_Dep_Tm', 'Leg_Arrv_Dt_Tm',
'Opr_Car_Cd', 'Leg_Dep_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail',
'ot_avail', 'total_seats', 'dest_lat', 'dest_long', 'geometry', 'duration_hours']]
city_source = ColumnDataSource(cities.drop('geometry', axis=1))
p1 = Figure(title='Flights',
plot_height=936,
plot_width=1560,
toolbar_location='below',
tools='pan, wheel_zoom, box_zoom, reset')
p1.xgrid.grid_line_color = None
p1.ygrid.grid_line_color = None # Add patch renderer to figure.
p1.patches('xs', 'ys', source=geosource,
fill_color=None,
line_color='gray',
line_width=0.25,
fill_alpha=1) # Create hover tool
slider_duration = Slider(title='Duration', start=0, end=int(np.round(cities.duration_hours.max(), 0)), step=1, value=12)
callback = CustomJS(args = dict(source=city_source),
code = """source.change.emit();""")
slider_duration.js_on_change('value', callback)
duration_filter = CustomJSFilter(args = dict(slider = slider_duration,
source = city_source),
code = """
var indices = [];
// iterate through rows of data source and see if each satisfies some constraint
for (var i = 0; i < source.get_length(); i++){
if (source.data['duration_hours'][i] <= slider.value){
indices.push(true);
} else {
indices.push(false);
}
}
return indices;
""")
#SEAT FILTER START
slider_seats = Slider(title='Seats', start=0, end=int(cities.total_seats.max()), step=1, value=10)
callback_seats = CustomJS(args = dict(source=city_source),
code = """source.change.emit();""")
slider_seats.js_on_change('value', callback_seats)
seats_filter = CustomJSFilter(args = dict(slider = slider_seats,
source = city_source),
code = """
var indices = [];
// iterate through rows of data source and see if each satisfies some constraint
for (var i = 0; i < source.get_length(); i++){
if (source.data['total_seats'][i] >= slider.value){
indices.push(true);
} else {
indices.push(false);
}
}
return indices;
""")
#SEAT FILTER END
columns = [TableColumn(field=Ci, title=Ci) for Ci in ['Leg_Orig', 'Leg_Dest', 'MAILG_CTY_NM', 'Opr_Car_Flt_Nbr', 'Leg_Arrv_Dt_Tm', 'd1_avail', 'cp_avail', 'mn_avail', 'total_seats', 'weather_desc', 'duration_hours']]
view = CDSView(source = city_source, filters = [duration_filter, seats_filter])
sites = p1.circle('dest_long', 'dest_lat', source = city_source, color = 'red',
size = 5, alpha = 0.3, view = view)
data_table = DataTable(source=city_source, columns=columns, width=1560, height=280, view= view)
p1.add_tools(HoverTool(renderers = [sites],line_policy='next',
tooltips = [('City','@MAILG_CTY_NM'),
('Departure Time','@Leg_Dep_Dt_Tm'),
('Seats','@seats'),
('Flight Time','@duration_hours' + ' hours'),
('weather', '@weather_desc' + ' low:' + '@low_temp' + ' high:' + '@high_temp' + ' rain:' + '@rain')]))
#city_pt = p1.circle('dest_long', 'dest_lat', source = newsource,
# color='red')
layout = column(p1, slider_duration, slider_seats,data_table)
curdoc().add_root(layout)