我想创建一个bokeh应用程序,可以根据某些属性过滤点。下面是我的用例的一个非常简单的代码示例,它使用复选框过滤绘图上的点。
from bokeh.plotting import ColumnDataSource, figure, curdoc
import bokeh.models as bmo
from bokeh.layouts import row
import numpy as np
def update_filter(selected_colors):
keep_indices = []
for i, color in enumerate(cds.data['color']):
if color2idx[color] in selected_colors:
keep_indices.append(i)
view.filters[0] = bmo.IndexFilter(keep_indices)
cds = ColumnDataSource(data=dict(
x=np.random.rand(10),
y=np.random.rand(10),
color=['red', 'green', 'blue', 'red', 'green',
'blue', 'red', 'green', 'blue', 'red'])
)
view = bmo.CDSView(source=cds, filters=[bmo.IndexFilter(np.arange(10))])
checkboxes = bmo.CheckboxGroup(labels=['red', 'green', 'blue'], active=[0, 1, 2])
color2idx = {'red': 0, 'green': 1, 'blue': 2}
checkboxes.on_change('active', lambda attr, old_val, new_val: update_filter(new_val))
fig = figure(plot_width=400, plot_height=400, title='Visualize')
fig.circle(x='x', y='y', fill_color='color', size=10, source=cds, view=view, legend_field='color')
curdoc().add_root(row(checkboxes, fig))
curdoc().title = 'Plot'然而,当我通过取消选中其中一个复选框来过滤指出时,它工作得很好,图例变得错误。下面是选择所有颜色时的屏幕截图:

这是取消选择其中一种颜色时的屏幕截图:

可以看到,当取消选中“绿色”的复选框时,“绿色”的图例变为红色。
我发现图例在CDSView上不能正常工作,这仍然是一个未解决的问题:https://github.com/bokeh/bokeh/issues/8010
因此,我写了下面的函数,它将修改图例,使其不会出错。
def update_legend():
# Find the indices in the CDS that are visible
filters = view.filters
visible_indices = set(list(range(len(cds.data['x']))))
for filter in filters:
visible_indices = visible_indices & set(filter.indices)
# Get a list of visible colors
visible_colors = set([cds.data['color'][i] for i in visible_indices])
# Create a dummy figure to obtain renderers
dummy_figure = figure(plot_width=0, plot_height=0, title='')
legend_items = []
# Does not work
for color in visible_colors:
renderer = dummy_figure.circle(x=[0], y=[0], fill_color=color, size=10)
legend_items.append(bmo.LegendItem(label=color, renderers=[renderer]))
fig.legend[0].items = legend_items并为复选框组添加了另一个事件回调:
checkboxes.on_change('active', lambda attr, old_val, new_val: update_legend())当我执行上述操作时,图例中的标签已更正,但现在图例中不会呈现字形。下面是相同的屏幕截图:

我做错了什么?我应该如何为图例创建GlyphRenderer,以便问题得到解决?
发布于 2021-06-29 00:47:26
这适用于Bokeh v2.1.1。除了原始代码之外,您还可以单击图例项来显示/隐藏圆圈。
from bokeh.plotting import ColumnDataSource, figure, curdoc
from bokeh.models import CheckboxGroup, Row, CDSView, IndexFilter
import numpy as np
colors = ['red', 'green', 'blue']
cds = ColumnDataSource(dict(x=np.random.rand(10),
y=np.random.rand(10),
color=['red', 'green', 'blue', 'red', 'green', 'blue', 'red', 'green', 'blue', 'red']))
def update_filter(selected_colors):
for i in range(len(colors)):
renderers[i].visible = True if i in selected_colors else False
checkboxes = CheckboxGroup(labels=colors, active=[0, 1, 2], width = 50)
checkboxes.on_change('active', lambda attr, old_val, new_val: update_filter(new_val))
fig = figure(plot_width=400, plot_height=400, title='Visualize')
views = [CDSView(source=cds, filters=[IndexFilter([i for i, x in enumerate(cds.data['color']) if x == color])]) for color in colors]
renderers = [fig.circle(x='x', y='y', fill_color='color', size=10, source=cds, view=views[i], legend=color) for i,color in enumerate(colors)]
fig.legend.click_policy = 'hide'
curdoc().add_root(Row(checkboxes, fig))
curdoc().title = 'Plot'结果:

https://stackoverflow.com/questions/68102763
复制相似问题