我正在追踪this great tutorial与Bokeh一起玩。
基本上,我有一个figure
并添加了两个独立的line
。一切都正确呈现,但是当我要更新时,即使我检查新的ColumnDataSource
是否已使用新值很好地更新也没有任何反应。
我使用以下命令进行渲染:bokeh serve --show my_app
这是我创建figure
的方式:
src_p6 = make_dataset(["select_a", "select_b"])
p6 = make_plot(src_p6)
select_selection = CheckboxGroup(labels=["select_a", "select_b"], active = [0, 1])
select_selection.on_change('active', update)
controls = WidgetBox(select_selection)
curdoc().add_root(column(controls, p6, width=1200))
def make_dataset(select_list):
if 'select_a' in select_list and 'select_b' in select_list:
tmp = pd.DataFrame({'time': df["time"],
'a': df["a"],
'b': df["b"]
})
elif 'select_a' in select_list and 'select_b' not in select_list:
tmp = pd.DataFrame({'time': df["time"],
'a': df["a"]
})
elif 'select_a' not in select_list and 'select_b' in select_list:
tmp = pd.DataFrame({'time': df["time"],
'b': df["b"]
})
else:
tmp = pd.DataFrame({'time': df["time"]
})
src = ColumnDataSource(tmp)
return src
def make_plot(plot_src):
p = figure(plot_width=1000, plot_height=600,
title="Line x2 with hover and update",
x_axis_label='Time',
y_axis_label='Values'
)
hover_content = [("Time", "@time")]
if 'a' in plot_src.data:
p.line(x='time', y='a', source=plot_src, legend="A", line_color="blue")
hover_content.append(("A", "@a"))
if 'b' in plot_src.data:
p.line(x='time', y='b', source=plot_src, legend="B", line_color="red")
hover_content.append(("B", "@b"))
p.add_tools(HoverTool(tooltips=hover_content))
return p
def update(attr, old, new):
print(src_p6.data)
select_to_plot = [select_selection.labels[i] for i in select_selection.active]
new_src = make_dataset(select_to_plot)
src_p6.data = new_src.data
print("**********************")
print(src_p6.data) # I see here that the data are well updated compared to the first print
我的传入数据是JSON,看起来像这样:
# {"data":[{"time":0,"a":123,"b":123},{"time":1,"a":456,"b":456},{"time":2,"a":789,"b":789}]}
# data = json.load(data_file, encoding='utf-8')
# df = pd.io.json.json_normalize(data['data'])
感谢您的见解
答案 0 :(得分:2)
这将无法正常运行:
src_p6.data = new_src.data
ColumnDataSource
是Bokeh中最复杂的对象之一,例如CDS上的.data
对象不是Python的简单命令,它具有许多特殊的工具,可实现高效流式传输。但是,它也与创建它的CDS有联系。从一个CDS中剥离.data
并将其分配给另一个CDS是行不通的。我们可能需要找到一种方法来投诉,但我不确定如何。
在任何情况下,您都需要从一个简单的Python字典中分配.data
,就像所有示例和演示一样:
src_p6.data = dict(...)
对于您的特定代码,这可能意味着让make_dataset
仅直接返回它直接创建的指令,而不是将它们放入数据帧中,然后从中制成CDS。
答案 1 :(得分:0)
首先感谢@bigreddot的时间和指导。
我最大的问题之一是我实际上并不想更新值,而只是显示/隐藏它,因此仅从源中删除它是行不通的。
在line
函数中用make_plot
语句添加if
也不起作用,因为它仅在第一次创建绘图时才被调用。对于更新,它会更新图中的值,但不会从头开始重构所有内容... 因此,如果仅从一行开始,即使有可能,我也不知道它将如何创建新行。 ..
我开始简化make_dataset
函数,使其仅返回一个简单的Python字典:
tmp = dict(time=df["time"], a=df["a"], b=df["b"])
但是当我想删除一行时,即使有更好的解决方案(我只是在这里与Bokeh一起玩),我还是使用了一个空数组:Line ON/OFF,Interactive legend
empty = np.empty(len(df["time"])); empty.fill(None)
tmp = dict(time=df["time"], a=df["a"], b=empty)
当我第一次创建我的情节时,我会做:
src_p6 = ColumnDataSource(data=make_dataset(["select_a", "select_b"]))
p6 = make_plot(src_p6)
并且更新功能使用基本的python字典更新.data
的{{1}}:
ColumnDataSource