使用选择或滑块散景更新地图工具提示 [英] Bokeh update map tooltip using select or slider

查看:57
本文介绍了使用选择或滑块散景更新地图工具提示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to update a worldmap tooltip using a slicer or dropdown select. I got following question which sorted the most of the stuff for a Bokeh Slider custom JS callback


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)

现在,我为世界地图复制了以下内容:

Now, I replicated the same for a worldmap as below:

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

But in this case, as soon as I click on the slider, tooltip data vanish away. World map input file can be found here to smoothly run the code: https://github.com/CrazyDaffodils/Interactive-Choropleth-Map-Using-Python/tree/master/bokeh-app/data

推荐答案

将鼠标从触发它的字形上移开一小段时间后,工具提示就会消失.

A tooltip disappears after a small delay after you move your mouse off the glyph that has triggered it.

目前,Bokeh没有任何内置的更改行为的方式.有一个开放的解决方案,您可能可以适应您的需要: https://github.com/bokeh/bokeh/issues/5724

Right now, Bokeh doesn't have any built-in way of changing that behavior. There's an open issue for that with a workaround that you might be able to adapt to your needs: https://github.com/bokeh/bokeh/issues/5724

这篇关于使用选择或滑块散景更新地图工具提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆