Добавление слайдера Bokeh делает приборную панель пустой - PullRequest
0 голосов
/ 10 января 2020

Я пытаюсь добавить ползунок для фильтрации городов, которые отображаются на карте мира. Когда я просто добавляю все города с кодом ниже, он работает нормально.

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)

Когда я пытаюсь добавить слайдер, чтобы я мог отфильтровать, какие города отображаются на карте (на основе времени полета из базового города, используя столбец «duration_hours» Я пытался изменить свой код на это:

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)

Вместо карты со всеми городами, показанными красными точками, я получаю пустой экран. Я не уверен, какую глупую ошибку я совершаю но я надеюсь, что кто-то может?

1 Ответ

0 голосов
/ 13 января 2020

Welp, мне пришлось немного переписать, но у меня все заработало правильно. Благодарим вас за то, что я украл шаблон кода.

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)
...