用于隐藏多个渲染器的 Bokeh 一个滑块
Bokeh one slider for hiding multiple renderers
我正在开发一个带有多个条形图的 Bokeh 应用程序。每个图表都有多个渲染器,一个用于每年的数据,所有图表都嵌入并 运行 在 Flask 上——一个图表的代码如下所示。
我想添加一个滑块,它将 show/hide 条对应于一年或几年的数据,但我只能在网上找到如何使滑块更改一个渲染器显示的数据,而不是完全摆脱它。我已经尝试了显示的两种方法 here。他们没有工作,因为:
- 我正在使用 Flask 而不是 Bokeh 服务器(我是一个高性能计算人员而不是 web-anything,并且 Flask 已经由其他人设置),并且
- 我无法弄清楚多个渲染器的 JS 回调。
有什么建议吗?提前致谢。
import datetime
import pandas as pd
from bokeh.layouts import widgetbox, column
from bokeh.models import Slider, HoverTool
from bokeh.plotting import ColumnDataSource, figure, show
from bokeh.embed import components
from bokeh.transform import dodge
from bokeh import palettes
BAR_GROUP_WIDTH = 0.6
MONTHS = [
'January',
'Febuary',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
data = pd.DataFrame.from_dict(
{'Month': ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
'2017': [11.6124, 7.11175, 9.366717, 11.071917, 4.849774, 10.0885, 14.81031, 15.486875, 14.877268, 14.025417, 11.203527, 11.09575],
'2018': [10.480874, 11.042208, 11.874903, 12.120542, 15.4275, 19.12525, 16.546917, 9.330083, 6.740833, 2.145, 5.919208, 15.946958],
'2019': [11.521308, 7.023, 9.282109, 10.518875, 12.664917, 9.953042, 13.494, 11.729083, 14.696792, 10.704042, 8.468698, 13.1605],
'2020': [11.162708, 7.276667, 15.194272, 16.654917, 19.552996, 20.480625, 14.800629, 7.722917, 19.260708, 18.052994, 17.488208, 19.442917],
'2021': [18.712944, 17.520792, 18.69113, 17.505542, 21.687413, 20.725637, 10.538542, 19.516708, 17.576167, 20.552875, 13.38375, 17.651667],
'2022': [17.027417, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
)
now = datetime.datetime.now()
years = [str(y) for y in range(2017, 2022)]
title = 'Test Plot'
source = ColumnDataSource(data=data)
p = figure(
x_range=MONTHS,
y_range=(0, data[years].max().max() * 1.25),
height=350, width=900,
title=title.center(100)
)
renderers = []
for ix, y in enumerate(years):
# Here I generate one renderer for each group of twelve bars corresponding to all months in a year
d = -BAR_GROUP_WIDTH / 2 + BAR_GROUP_WIDTH / (len(years) - 1) * ix
r = p.vbar(x=dodge('Month', d, range=p.x_range), top=y, width=BAR_GROUP_WIDTH / len(years),
source=source, line_color="white",
color=palettes.Category10[len(years)][ix],
legend_label=y
)
tooltip = [
('YEAR', y),
('MONTH', '@Month'),
('TOTAL', f'@{y}')
]
p.add_tools(HoverTool(tooltips=tooltip, renderers=[r]))
renderers.append(r)
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"
# How do I make this slider do what I want it to do?
slider = Slider(start=2017, end=now.year, value=now.year, step=1, title="Range")
layout = column(p, widgetbox(slider))
show(layout)
# # My application is running on Flask and I'm embedding Bokeh components, so I actually use components rather than show.
# script, div = components(layout)
# return (script, div)
如果这就是您要找的
您可以使用每个渲染器都有一个属性 visible
。您可以将其设置为 True
或 False
。
您必须导入 CustomJS
然后编写一些 JavaScript 代码并通过回调将其连接到滑块。
callback = CustomJS(args=dict(renderers=p.renderers, year=2017), code="""
const f = cb_obj.value;
if(cb_obj.value == 2022){
for(let r of renderers)
r.visible = true
}
else{
for(let r of renderers)
r.visible = false
renderers[f-year].visible = true
}
""")
slider = Slider(start=2017, end=now.year, value=now.year, step=1, title="Range")
slider.js_on_change('value', callback)
在此示例的实现中,如果您 select 2022 年,则所有渲染器都设置为可见,否则只有 selected 年份的渲染器可见,其他所有渲染器都不可见。
我正在开发一个带有多个条形图的 Bokeh 应用程序。每个图表都有多个渲染器,一个用于每年的数据,所有图表都嵌入并 运行 在 Flask 上——一个图表的代码如下所示。
我想添加一个滑块,它将 show/hide 条对应于一年或几年的数据,但我只能在网上找到如何使滑块更改一个渲染器显示的数据,而不是完全摆脱它。我已经尝试了显示的两种方法 here。他们没有工作,因为:
- 我正在使用 Flask 而不是 Bokeh 服务器(我是一个高性能计算人员而不是 web-anything,并且 Flask 已经由其他人设置),并且
- 我无法弄清楚多个渲染器的 JS 回调。
有什么建议吗?提前致谢。
import datetime
import pandas as pd
from bokeh.layouts import widgetbox, column
from bokeh.models import Slider, HoverTool
from bokeh.plotting import ColumnDataSource, figure, show
from bokeh.embed import components
from bokeh.transform import dodge
from bokeh import palettes
BAR_GROUP_WIDTH = 0.6
MONTHS = [
'January',
'Febuary',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
data = pd.DataFrame.from_dict(
{'Month': ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
'2017': [11.6124, 7.11175, 9.366717, 11.071917, 4.849774, 10.0885, 14.81031, 15.486875, 14.877268, 14.025417, 11.203527, 11.09575],
'2018': [10.480874, 11.042208, 11.874903, 12.120542, 15.4275, 19.12525, 16.546917, 9.330083, 6.740833, 2.145, 5.919208, 15.946958],
'2019': [11.521308, 7.023, 9.282109, 10.518875, 12.664917, 9.953042, 13.494, 11.729083, 14.696792, 10.704042, 8.468698, 13.1605],
'2020': [11.162708, 7.276667, 15.194272, 16.654917, 19.552996, 20.480625, 14.800629, 7.722917, 19.260708, 18.052994, 17.488208, 19.442917],
'2021': [18.712944, 17.520792, 18.69113, 17.505542, 21.687413, 20.725637, 10.538542, 19.516708, 17.576167, 20.552875, 13.38375, 17.651667],
'2022': [17.027417, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
)
now = datetime.datetime.now()
years = [str(y) for y in range(2017, 2022)]
title = 'Test Plot'
source = ColumnDataSource(data=data)
p = figure(
x_range=MONTHS,
y_range=(0, data[years].max().max() * 1.25),
height=350, width=900,
title=title.center(100)
)
renderers = []
for ix, y in enumerate(years):
# Here I generate one renderer for each group of twelve bars corresponding to all months in a year
d = -BAR_GROUP_WIDTH / 2 + BAR_GROUP_WIDTH / (len(years) - 1) * ix
r = p.vbar(x=dodge('Month', d, range=p.x_range), top=y, width=BAR_GROUP_WIDTH / len(years),
source=source, line_color="white",
color=palettes.Category10[len(years)][ix],
legend_label=y
)
tooltip = [
('YEAR', y),
('MONTH', '@Month'),
('TOTAL', f'@{y}')
]
p.add_tools(HoverTool(tooltips=tooltip, renderers=[r]))
renderers.append(r)
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"
# How do I make this slider do what I want it to do?
slider = Slider(start=2017, end=now.year, value=now.year, step=1, title="Range")
layout = column(p, widgetbox(slider))
show(layout)
# # My application is running on Flask and I'm embedding Bokeh components, so I actually use components rather than show.
# script, div = components(layout)
# return (script, div)
如果这就是您要找的
您可以使用每个渲染器都有一个属性 visible
。您可以将其设置为 True
或 False
。
您必须导入 CustomJS
然后编写一些 JavaScript 代码并通过回调将其连接到滑块。
callback = CustomJS(args=dict(renderers=p.renderers, year=2017), code="""
const f = cb_obj.value;
if(cb_obj.value == 2022){
for(let r of renderers)
r.visible = true
}
else{
for(let r of renderers)
r.visible = false
renderers[f-year].visible = true
}
""")
slider = Slider(start=2017, end=now.year, value=now.year, step=1, title="Range")
slider.js_on_change('value', callback)
在此示例的实现中,如果您 select 2022 年,则所有渲染器都设置为可见,否则只有 selected 年份的渲染器可见,其他所有渲染器都不可见。