Javascript 使用Bokeh中的复选框小部件隐藏或显示动态行数的行
我试图在我的博克图中添加复选框,以便在我的图中隐藏或显示不同的线。我从github中找到了一些代码,并对其进行了修改以达到我的目的。请查看下面的代码Javascript 使用Bokeh中的复选框小部件隐藏或显示动态行数的行,javascript,python,python-2.7,bokeh,Javascript,Python,Python 2.7,Bokeh,我试图在我的博克图中添加复选框,以便在我的图中隐藏或显示不同的线。我从github中找到了一些代码,并对其进行了修改以达到我的目的。请查看下面的代码 for data, name, color in zip([AAPL, IBM, MSFT, GOOG], ["AAPL", "IBM", "MSFT", "GOOG"], Spectral4): df = pd.DataFrame(data) source = ColumnDataSo
for data, name, color in zip([AAPL, IBM, MSFT, GOOG], ["AAPL", "IBM", "MSFT", "GOOG"], Spectral4):
df = pd.DataFrame(data)
source = ColumnDataSource(data = dict(date = pd.to_datetime(df['date']), close = df['close']))
plt = fig.line('date', 'close', line_width=2, color=color, alpha=0.8,
muted_color=color, muted_alpha=0.2, legend = name, source=source)
graph_labels.append(name)
plots.append(plt)
checkbox = CheckboxGroup(labels = graph_labels, active = [0,1,2,3])
checkbox.callback = CustomJS(args = dict(line0 = plots[0], line1=plots[1], line2=plots[2], line3=plots[3]), code="""
//console.log(cb_obj.active);
line0.visible = false;
line1.visible = false;
line2.visible = false;
line3.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;
} else if (cb_obj.active[i] == 2) {
line2.visible = true;
} else if (cb_obj.active[i] == 3) {
line3.visible = true;
}
}
""")
layout = row(fig, widgetbox(checkbox), sizing_mode='fixed')
show(layout)
这段代码工作得很好。然而,我的要求是别的。在我的情况下,每次运行代码时,PLT的数量都会不同,因为我的数据不同。所以我试图修改这段代码,但还没有成功
我所做的改变是
checkbox = CheckboxGroup(labels = graph_labels, active = list(range(0, len(plots))))
arg_list = []
for idx in range(0, len(plots)):
arg_list.append('line' + str(idx))
arg_list.append(plots[idx])
i = iter(arg_list)
checkbox.callback = CustomJS(args = dict(izip(i, i)), code="""
// Here I don't know how to use dynamic names for line0 and line1 and use them to control their visibility
// As type of line0 is object and if I 'm trying to make a dynamic string I can't convert it to object and it fails
我也试过使用
source = ColumnDataSource(data = dict( ... ) ...
callback = CustomJS(args=dict(source=source), code="""
但它也失败了,没有显示任何阴谋。
我使用的是Bokeh和Python2.7的最新版本
我们非常感谢您的任何建议!!:) 您可以这样做:
from bokeh.io import show
from bokeh.plotting import figure
from bokeh.models import CustomJS, CheckboxGroup
from bokeh.layouts import Row
from bokeh.palettes import Category20_20
from random import random,choice
N_lines = int(100*random())/10 # undefined but known from the start number of lines.
x= range(3)
fig = figure()
args = []
code = "active = cb_obj.active;"
for i in range(N_lines):
glyph = fig.line(x,[random() for j in x],color=choice(Category20_20))
args += [('glyph'+str(i),glyph)]
code += "glyph{}.visible = active.includes({});".format(i,i)
checkbox = CheckboxGroup(labels=[str(i) for i in range(N_lines)],active=range(N_lines))
checkbox.callback = CustomJS(args={key:value for key,value in args},code=code)
show(Row(fig,checkbox))
这将根据行数生成回调代码。
因为您要求代码适应您的数据,所以您当然可以根据数据确定行数
之后,如果还希望通过交互动态添加行,则需要更新:
复选框.标签
(只需添加一个标签名称)
checkbox.active
(将其设置为包含一个以上数字的范围()列表)
checkbox.callback
(多了一对“args”和一个“code”条目)事实上,我从下面的帖子中找到了这个问题的答案
在评论部分,user2561747提出了类似的建议。起初,我遇到了一些问题,因为我想使用悬停工具,我试图用不同的名称命名每个情节,然后诸如此类
for column, color in zip(df.columns.values, Spectral4):
......
......
plt = fig.line('date', 'value', name = column, line_width = 2, color = color, alpha = 0.8,
muted_color = color, muted_alpha = 0.2, legend = column, source = source)
graph_labels.append(column)
plots.append(plt)
......
......
checkbox = CheckboxGroup(labels = graph_labels, active = list(range(0, len(plots))))
checkbox.callback = CustomJS.from_coffeescript(args = dict(plot = fig, checkbox = checkbox), code="""
rends = [];
rends.push plot.select(label) for label in checkbox.labels;
rends[i].visible = i in checkbox.active for i in [0...rends.length];
""")
我从来都不知道问题出在哪里,但我最终把所有的情节都命名为“可隐藏的”,这也适用于悬停工具。最后的代码是这样的
checkbox.callback = CustomJS.from_coffeescript(args = dict(plot = fig, checkbox = checkbox), code="""
rends = plot.select("hideable");
rends[i].visible = i in checkbox.active for i in [0...rends.length];
""")
如果有人能发现第一种方法的问题,那就太棒了。我在浏览器控制台中完全没有看到任何错误,但是在这两种情况下,rends数组的元素具有不同的结构 非常感谢您的回复。不幸的是,这种方法并不适合我。当我尝试在您建议的修改后运行我的代码时,它根本没有显示任何绘图。@neo我提供的代码在所有浏览器中都能正常工作。当你把它调整到你的时候,你会错过什么吗?很好的答案。我想在for循环之外这样做:只是让其他人知道,
code
类似于active=cb_obj.active;glyph0.visible=活动。包括(0);glyph1.visible=活动。包括(1)
@FrancescoBoi谢谢,但是请注意,在bokeh中实现交互式图例以显示/隐藏线条之前,现在我建议使用它,而不是创建自定义复选框