0

我正在尝试使用切片器或下拉选择更新世界地图工具提示。我得到了以下问题,它为Bokeh Slider 自定义 JS 回调排序了大部分内容


import pandas as pd
import random
from datetime import timedelta

df = pd.DataFrame({'base' : ["2017-01-01" for t in range(10000)],
    'Date' : [random.randint(0, 1035) for t in range(10000)], 
                   'Sales' : [random.random() for t in range(10000)]})
df['base'] = pd.to_datetime(df['base'])
df["Date2"] = df.apply(lambda x: x["base"] + timedelta(days=x['Date']), axis=1)
df.drop(['base', 'Date'], axis=1, inplace=True)
df.set_index('Date2', inplace=True)
df['month'] = df.index.month
df['year'] = df.index.year
df['day'] = df.index.day
df.head()

from bokeh.models.widgets import Slider,Select
from bokeh.io import output_notebook, show, output_file

from bokeh.layouts import widgetbox, column
from bokeh.models import Slider, ColumnDataSource, CustomJS
from bokeh.plotting import figure, curdoc
from bokeh.core.properties import value
from bokeh.models.ranges import FactorRange
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import ColumnDataSource, CDSView, IndexFilter, BooleanFilter, HoverTool


source1=df.groupby(['year','month','day'], as_index = False).sum()
source = source1[source1['year']== 2017]
sourcex = source[source['month'] ==1]
Overall=ColumnDataSource(source)
Curr=ColumnDataSource(sourcex)
boolinit = source['month']==1
view = CDSView(source=Overall, filters=[BooleanFilter(boolinit)])
hover3 = HoverTool(tooltips = [('day', '@day'),('Sales','@{Sales}{0,0}')],
                   formatters = {'day': 'datetime','Sales': 'numeral'})

p =  figure(title='YEARLY SALES',  plot_width=600, plot_height=400, min_border=3,
tools = [hover3,'box_zoom','wheel_zoom', 'pan','reset'],  
toolbar_location="above")

r = p.vbar(x='day', top='Sales', width=0.2, color='#e8bc76', source=Curr)
p.xaxis.axis_label = 'Day'
p.xaxis.axis_label_text_font_style = 'normal'
p.xaxis.axis_label_text_font_size = '12pt'



callback = CustomJS(args=dict(source=Overall, sc=Curr), code="""       
        var f = select.value;
        sc.data['day'] = [];
        sc.data['Sales'] = [];
        for (var i = 0; i <= source.get_length(); i++){
          if (source.data['month'][i] == f){
            sc.data['day'].push(source.data['day'][i])
            sc.data['Sales'].push(source.data['Sales'][i])
          }
        }
        sc.change.emit();
    """)
select = Select(options=["1","2","3"], title="Month", callback=callback)
callback.args["select"] = select

layout = column(select, p)
#Display plot inline in Jupyter notebook
output_notebook()
output_file("Filterdata.html")
show(layout)

现在,我为世界地图复制了相同的内容,如下所示:

import pandas as pd
import geopandas as gpd
current_week = 4
shapefile = 'data/countries_110m/ne_110m_admin_0_countries.shp'
gdf = gpd.read_file(shapefile)[['ADMIN', 'ADM0_A3', 'geometry']]
gdf.columns = ['country', 'country_code', 'geometry']
gdf = gdf.drop(gdf.index[159])
df = pd.DataFrame({'Country':['India','India'],
              'SalesGain':['10%','20%'],
                   'Week':[4,5],
                   'Color':[0.2,0.4]
             })

import json
from bokeh.models.widgets import Slider,Select
from bokeh.io import output_notebook, show, output_file
from bokeh.layouts import widgetbox, column
from bokeh.models import Slider, ColumnDataSource, CustomJS
from bokeh.plotting import figure, curdoc
from bokeh.core.properties import value
from bokeh.models.ranges import FactorRange
from bokeh.palettes import brewer
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import ColumnDataSource, CDSView, IndexFilter, BooleanFilter, HoverTool,GeoJSONDataSource, LinearColorMapper, ColorBar

from bokeh.plotting import figure, output_file, show
output_file("worldmap.html")


merged = gdf.merge(df, left_on = 'country', right_on = 'Country', how = 'left')
merged_json = json.loads(merged.to_json())
json_data = json.dumps(merged_json)
geosource_all = GeoJSONDataSource(geojson =  json_data)

df_curr = df[df['Week']==current_week]
merged_curr = gdf.merge(df_curr, left_on = 'country', right_on = 'Country', how = 'left')
merged_json_curr = json.loads(merged_curr.to_json())
json_data_curr = json.dumps(merged_json_curr)
geosource_curr = GeoJSONDataSource(geojson =  json_data_curr)


# boolinit = merged['Week']!=current_week
boolinit = merged['Week']==current_week
view = CDSView(source=geosource_all, filters=[BooleanFilter(boolinit)])
hover3 = HoverTool(tooltips = [('Country', '@Country'),('Sales','@SalesGain')])

#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 = 12, nan_color = '#d9d9d9')
#Define custom tick labels for color bar.
tick_labels = {'0': '0', '2':'2%',  '4':'4%',  '6':'6%', '8':'8%','10':'10%','12':'12%'}
#Create color bar. 
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=6,width = 500, height = 20,
                     border_line_color=None,location = (0,0), orientation = 'horizontal', major_label_overrides = tick_labels)


#Create figure object.
p =  figure(title='Covid-19 Impact',  plot_width=900, plot_height=600, min_border=3,
            tools = [hover3,'box_zoom','wheel_zoom', 'pan','reset'],toolbar_location="above")

p.title.text_font_size = '20pt'
p.title.text_color = "darkblue"
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None


#Add patch renderer to figure. 
p.patches('xs','ys', source = geosource_curr,fill_color = {'field' :'Color', 'transform' : color_mapper},
          line_color = 'black', line_width = 0.25, fill_alpha = 1)
p.add_layout(color_bar, 'below')


callback = CustomJS(args=dict(source=geosource_all, sc=geosource_curr), code="""       
        var f = slider.value;
        sc.data['Country'] = [];
        sc.data['Week'] = [];
        sc.data['SalesGain'] = [];
        for (var i = 0; i <= source.get_length(); i++){
          if ((source.data['Week'][i] == f ) || (source.data['Country'][i] == null) ){
            sc.data['SalesGain'].push(source.data['SalesGain'][i])
            sc.data['Week'].push(source.data['Week'][i])
            sc.data['Country'].push(source.data['Country'][i])
          }
        }
        sc.change.emit();
    """)
# select = Select(options=["201951","201952","201953"], title="Week", callback=callback)
# callback.args["select"] = select
# layout = column(select, p)

slider = Slider(start=1, end=5, value=current_week, step=1, title="Month", callback=callback)
callback.args["slider"] = slider
layout = column(slider, p)

#Display plot inline in Jupyter notebook
output_notebook()

show(layout)

但是在这种情况下,只要我单击滑块,工具提示数据就会消失。世界地图输入文件可以在这里找到顺利运行代码: https ://github.com/CrazyDaffodils/Interactive-Choropleth-Map-Using-Python/tree/master/bokeh-app/data

4

1 回答 1

0

将鼠标移离触发它的字形后,工具提示会在一小段延迟后消失。

目前,Bokeh 没有任何内置方法来改变这种行为。有一个未解决的问题,您可能能够适应您的需求:https ://github.com/bokeh/bokeh/issues/5724

于 2020-03-24T20:35:35.693 回答