Python 散景 CustomJS RadioGroup

Python Bokeh CustomJS RadioGroup

我对 Python 和 Pandas 相当有经验,但对 Bokeh 包还是个新手,过去几天一直在努力完成这项任务,但没有任何进展。我正在构建一个仪表板来显示数据,使用单选按钮 select/show 同一图上的不同行会非常有帮助。我一直在关注此处 (https://github.com/bokeh/bokeh/issues/3715) 中的示例,我可以使用复选框正常工作。我已将第 21 行中的 "CheckboxGroup" 以及 "active" 参数更改为 "RadioGroup"。结果是,当我更改单选按钮的选择时,两条绘制的线都消失了,再也没有回来。我不明白为什么 CheckboxGroup 有效而 RadioGroup 无效,考虑到它们有多么相似并且它们都使用 "active" 事件进行回调。有人可以指出我的错误吗?

import numpy as np

from bokeh.io import show
from bokeh.layouts import widgetbox
from bokeh.models.widgets import CheckboxGroup, RadioGroup
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.layouts import column, row
from bokeh.plotting import figure

t = np.arange(0.0, 2.0, 0.01)
s = np.sin(3*np.pi*t)
c = np.cos(3*np.pi*t)

source = ColumnDataSource(data=dict(t=t, s=s, c=c))

plot = figure(plot_width=400, plot_height=400)
a = plot.line('t', 's', source=source, line_width=3, line_alpha=0.6, 
line_color='blue')
b = plot.line('t', 'c', source=source, line_width=3, line_alpha=0.6,
line_color='red')

checkbox = RadioGroup(labels=["Cosinus", "Sinus"], active=0)

checkbox.callback = CustomJS(args=dict(line0=a, line1=b), code="""   
    //console.log(cb_obj.active);
    line0.visible = false;
    line1.visible = false;
    for (i in cb_obj.active) {
        //console.log(cb_obj.active[i]);
        if (cb_obj.active[i] == 0) {
            line0.visible = true;
        } else if (cb_obj.active[i] == 1) {
            line1.visible = true;
        }
    }
""")

layout = row(plot, widgetbox(checkbox))

show(layout)

我认为使用 multi_line 方法绘制此图更容易。然后您可以选择在回调中选择哪些行,如下所示。

import numpy as np

from bokeh.io import show
from bokeh.layouts import widgetbox
from bokeh.models.widgets import CheckboxGroup, RadioGroup
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.layouts import column, row
from bokeh.plotting import figure

t = np.arange(0.0, 2.0, 0.01)
s = np.sin(3*np.pi*t)
c = np.cos(3*np.pi*t)

source = ColumnDataSource(data=dict(t=[t]*2, s=[s,c], colors = ['red', 'blue']))

plot = figure(plot_width=400, plot_height=400)
plot.multi_line('t', 's',line_color='colors' ,source=source)

checkbox = RadioGroup(labels=["Cosinus", "Sinus"], active=0)

checkbox.callback = CustomJS(args=dict(s=source), code="""   
    s.selected['1d'].indices = [cb_obj.active]
    s.trigger('change');
""")

layout = row(plot, widgetbox(checkbox))

show(layout)

在 radioboxgroup 中,您一次只能有一个活动值,因此当您尝试遍历一个整数时,您的 for 循环毫无用处。这是您更正的代码

checkbox.callback = CustomJS(args=dict(line0=a, line1=b), code="""   
    line0.visible = false;
    line1.visible = false;

    if (cb_obj.active == 0) {
        line0.visible = true;
    } else if (cb_obj.active == 1) {
        line1.visible = true;
    }
""")

有一个更好的方法,如果你有很多行,你可以在循环中使用 "labels" 列表的长度

line_list = [line0,line1];

lab_len=cb_obj.labels.length;

for (i=0;i<lab_len;i++) {
if (cb_obj.active == i) {
line_list[i].visible = true;
} else {
line_list[i].visible = false;
}
}

在复选框组中,"active" 属性是一个索引列表。您只需更改 if 条件即可使代码正常工作:

checkbox = CheckboxGroup(labels=["Cosinus", "Sinus"], active=[0,1])

checkbox.callback = CustomJS(args=dict(line0=a, line1=b), code="""   
    line_list = [line0,line1];

    lab_len=cb_obj.labels.length;

    for (i=0;i<lab_len;i++) {
    if (cb_obj.active.includes(i)) {
    line_list[i].visible = true;
    } else {
    line_list[i].visible = false;
    }
    }
""")

如果您想让用户轻松控制字形的可见性,那么从 Bokeh 0.12.5 开始,您可以让图例具有交互性,以便在用户单击图例条目时隐藏字形或使其静音:

如果要完全隐藏字形,请将图例的 click_policy 设置为 "hide"

p = figure()
p.circle([1,2,3], [4,5,6], legend="foo")
p.square([1,2,3], [7,9,8], legend="bar")
p.legend.click_policy = "hide"

您还可以将策略设置为静音:

p.legend.click_policy = "mute"

但是您需要指定每个字形的 "muted" 外观,例如

p.circle([1,2,3], [4,5,6], muted_alpha=0.2, legend="foo")