我正在尝试在散景图中添加复选框,以便我可以在我的情节中隐藏或显示不同的线条。我从github找到了一些代码并修改它以实现我的目的。请查看以下代码,
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)
此代码完美无缺。然而,我的要求是别的。在我的情况下,每次运行代码时,plts的数量都会不同,因为我的数据不同。所以我试图修改这段代码,但还没有取得任何成功。
我所做的更改是
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和python 2.7 任何建议都是高度赞赏的,并提前感谢!! :)
答案 0 :(得分:0)
您可以这样做:
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.labels
(只需添加一个标签名称)
checkbox.active
(将其设置为另一个数字的range()列表)
checkbox.callback
(还有一对用于“args”,另外一对用于“代码”)
答案 1 :(得分:-1)
其实我从以下帖子中找到了这个问题的答案
How to interactively display and hide lines in a Bokeh plot?
在评论部分,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数组的元素在两种情况下都有不同的结构。