Ahs*_*566 6 python interaction data-visualization python-3.x bokeh
我正在开发散景中的地理仪表板。在散景中使用悬停工具提示相当容易,但是当我悬停在一个字段上时我想填充一个 div。
Python 版本:3.5.2
散景版本:0.13.0
1. 这是仪表板的主视图。

2. 所需输出

我想添加两个交互,
3. 数据:

4. 代码:
from bokeh.io import show, output_notebook, output_file
from bokeh.models import (
GeoJSONDataSource,
HoverTool,
LinearColorMapper,
ColorBar,
BasicTicker,
PrintfTickFormatter,
LogColorMapper,
Range1d,
Plot,
Text
)
from bokeh.plotting import figure
import geopandas as gpd
with open('/home/drogon/Desktop/Rescue-1122-project/punjab_districts(area_pop_den).geojson', 'r') as f:
geo_source = GeoJSONDataSource(geojson=f.read())
df = gpd.read_file('/home/drogon/Desktop/Rescue-1122-project/punjab_districts(area_pop_den).geojson')
print(df.density)
density = df['density']
colors = ['#000003', '#3B0F6F', '#8C2980', '#DD4968', '#FD9F6C']
colors.reverse()
color_mapper = LogColorMapper(palette=colors, low=density.min(), high=density.max())
TOOLS = "pan,wheel_zoom,box_zoom,reset,hover,save"
p = figure(title="Punjab Districts", tools=TOOLS, x_axis_location=None, y_axis_location=None, width=800, height=800)
p.grid.grid_line_color = None
p.title.text_font_size = '30pt'
p.patches('xs', 'ys', fill_alpha=0.9, fill_color={'field': 'density', 'transform': color_mapper},
line_color='white', line_width=1, source=geo_source)
hover = p.select_one(HoverTool)
hover.point_policy = "follow_mouse"
hover.tooltips = [("District", "@district"),
("Density", "@density"),
("Area", "@area")]
color_bar = ColorBar(color_mapper=color_mapper, major_label_text_font_size="10pt",
ticker=BasicTicker(desired_num_ticks=8),
formatter=PrintfTickFormatter(format="%d"),
label_standoff=10, border_line_color=None, location=(0, 0))
p.add_layout(color_bar, 'right')
show(p)
Run Code Online (Sandbox Code Playgroud)
小智 0
由于您没有将其包含在您的问题中,因此我无法获得与您完全相同的数据。相反,我在Kaggle上使用了这个 json 文件并结合了Wikipedia上提供的信息
由于这是一个老问题,请注意版本与您的版本不同:
Python版本:3.8.2
散景版本:3.0.1
为了向绘图添加交互,您需要实现 JavaScript 回调来更改 Div 对象的文本。有关该主题的更多详细信息,请查看有关 JavaScript 回调的 Bokeh 文档
from bokeh.io import show, output_notebook, output_file
from bokeh.models import (
GeoJSONDataSource,
HoverTool,
LinearColorMapper,
ColorBar,
BasicTicker,
PrintfTickFormatter,
LogColorMapper,
Range1d,
Plot,
Text,
Div,
CustomJS,
TapTool
)
from bokeh.plotting import figure
from bokeh.layouts import column, row
from bokeh import events
import geopandas as gpd
with open('data/punjab_districts_updated.geojson', 'r') as f:
geo_source = GeoJSONDataSource(geojson=f.read())
df = gpd.read_file('data/punjab_districts_updated.geojson')
density = df['density']
colors = ['#000003', '#3B0F6F', '#8C2980', '#DD4968', '#FD9F6C']
colors.reverse()
color_mapper = LogColorMapper(palette=colors, low=density.min(), high=density.max())
TOOLS = "pan,wheel_zoom,box_zoom,tap,reset,save"
p = figure(title="Punjab Districts", tools=TOOLS, x_axis_location=None, y_axis_location=None, width=800, height=800)
p.grid.grid_line_color = None
p.title.text_font_size = '30pt'
div_district = Div(width=300, height=400)
div_info = Div(width=300)
# You need a layout to combine your map plot with the text boxes
layout = row(p, column(div_district, div_info))
p.patches('xs', 'ys', fill_alpha=0.9, fill_color={'field': 'density', 'transform': color_mapper},
line_color='white', line_width=1, source=geo_source)
# This JavaScript code will update the district name at the top right of your plot
code = """
const indices = cb_data.index.indices;
if (indices.length > 0){
div_text.text = "<span style='float: left; clear: left; font-size: 25pt'><b>District name</b><br>" + district[indices[0]] + "</span>";
}
else {
div_text.text = "<span style='float: left; clear: left; font-size: 25pt'><b>District name</b><br> </span>";
}
"""
callback = CustomJS(args={'district': df.district, 'div_text': div_district}, code=code)
# When you add the Hover tool to the plot, you can specify a callback to keep the hover tooltips
p.add_tools(HoverTool(tooltips=[("District", "@district"),
("Density", "@density"),
("Area", "@area")],
point_policy= "follow_mouse",
callback=callback))
# In this case, we will display pieces of information on the district each time the selection changes in the data source of the plot
callback_tap = CustomJS(args=dict(s=geo_source, district=df.info_district, div_text=div_info), code="""
const indices = s.selected.indices;
if (indices.length > 0) {
div_text.text = "<span style='float: left; clear: left; font-size: 25pt'><b>District info</b><br>" + district[indices[0]] + "</span>";
}
else {
div_text.text = "<span style='float: left; clear: left; font-size: 25pt'><b>District info</b><br></span>";
}
""")
geo_source.selected.js_on_change('indices', callback_tap)
color_bar = ColorBar(color_mapper=color_mapper, major_label_text_font_size="10pt",
ticker=BasicTicker(desired_num_ticks=8),
formatter=PrintfTickFormatter(format="%d"),
label_standoff=10, border_line_color=None, location=(0, 0))
p.add_layout(color_bar, 'right')
show(layout)
Run Code Online (Sandbox Code Playgroud)