How to dynamically hide glyphs and legend items with Bokeh

回眸只為那壹抹淺笑 提交于 2021-01-01 06:29:35

问题


I am trying to implement checkboxes in bokeh where each checkbox should show/hide the line associated with it. I'm aware it's possible to achieve this with legends, but I want this effect to happen in two plots at the same time. Also, the legend should update as well. In the example below the checkboxes appear, but do nothing. I am clearly not grasping how to update de dataframe used as source. Thanks for any help.

from bokeh.io import show, curdoc
from bokeh.models import  HoverTool, ColumnDataSource, Legend
from bokeh.plotting import figure
from bokeh.palettes import Category10
from bokeh.models.widgets import CheckboxGroup
from bokeh.layouts import row
import pandas as pd

def update(atrr, old, new):
        lines_to_plot = [checkbox_group.labels[i] for i in checkbox_group.active]
        cols = ['x']
        for label in lines_to_plot:
            cols += [label + 'y']
            cols += [label]
        newdf = df0[cols] 
        source.data.update(ColumnDataSource(newdf))    

df0 = pd.DataFrame({'x': [1, 2, 3], 'Ay' : [1, 5, 3], 'A': [0.2, 0.1, 0.2], 'By' : [2, 4, 3], 'B':[0.1, 0.3, 0.2]})

columns = ['A', 'B']
checkbox_group = CheckboxGroup(labels=columns, active=[0, 1])

tools_to_show = 'box_zoom,save,hover,reset'
p = figure(plot_height =300, plot_width = 1200, 
           toolbar_location='above',
           tools=tools_to_show)

legend_it = []
color = Category10[10]
columns = ['A', 'B']
source = ColumnDataSource(df0)
for i, col in enumerate(columns):
    c = p.line('x', col, source=source, name=col, color=color[i])
    legend_it.append((col, [c]))


legend = Legend(items=legend_it, location=(5,114))#(0, -60))

p.add_layout(legend, 'right')

hover = p.select(dict(type=HoverTool))
hover.tooltips = [("Name","$name"), ("Aux", "@$name")]
hover.mode = 'mouse'

layout = row(p,checkbox_group)

checkbox_group.on_change('active', update)

curdoc().add_root(layout)

回答1:


You will have to manage LegendItem objects manually. Here is a complete example:

import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import row
from bokeh.palettes import Viridis3
from bokeh.plotting import figure
from bokeh.models import CheckboxGroup, Legend, LegendItem

p = figure()
props = dict(line_width=4, line_alpha=0.7)
x = np.linspace(0, 4 * np.pi, 100)
l0 = p.line(x, np.sin(x), color=Viridis3[0], **props)
l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], **props)
l2 = p.line(x, np.tan(x), color=Viridis3[2], **props)

legend_items = [LegendItem(label="Line %d" % i, renderers=[r]) for i, r in enumerate([l0, l1, l2])]
p.add_layout(Legend(items=legend_items))

checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], width=100)

def update(attr, old, new):
    l0.visible = 0 in checkbox.active
    l1.visible = 1 in checkbox.active
    l2.visible = 2 in checkbox.active
    p.legend.items = [legend_items[i] for i in checkbox.active]

checkbox.on_change('active', update)

layout = row(checkbox, p)
curdoc().add_root(layout)


来源:https://stackoverflow.com/questions/51342213/how-to-dynamically-hide-glyphs-and-legend-items-with-bokeh

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!