我正在使用以下代码创建一个简单的情节:
from ipywidgets import interact
import numpy as np
from bokeh.io import push_notebook, show, output_notebook
from bokeh.plotting import figure
output_notebook()
x = np.linspace(0, 2*np.pi, 2000)
y = np.sin(x)
p = figure(title="simple line example", plot_height=300, plot_width=600, y_range=(-5,5),
background_fill_color='#efefef')
show(p)
我的目标是通过使用以下代码将bokeh的交互性引入此图:
r1=p.line(x, y)
def update(f, w=1, A=1, phi=0):
if f == "sin": func = np.sin
elif f == "cos": func = np.cos
for k in range(1,4):
r1=p.line(x, y)
r1.data_source.data['y'] = A * func(w * k*x + phi)
push_notebook()
并使用以下代码显示和更新图:
show(p, notebook_handle=True)
interact(update, f=["sin", "cos"], w=(0,50), A=(1,10), phi=(0, 20, 0.1))
运行上面的代码后,我将得到以下结果:
我期望通过更改phi,A等变量来更新包括4条线的整个图。但是当我为将罪变成cos,看起来像这样:
这意味着图例确实“更新”,但覆盖了旧图上的新数据。我在这里想念什么?而且我想保持循环。
答案 0 :(得分:1)
我在这里想念什么?
两件事:
push_notebook
专用于对现有地块进行增量更新,不替换其中的任何内容
每次调用p.line
都会在绘图中添加 new 行。
如果您只希望有一组固定的行可以响应窗口小部件而更新,则您的回调函数根本不应调用p.line
。您应该一次设置所需的行。然后在回调中,仅在调用push_notebook
来更新JavaScript端之前更新这些行的数据源。
此外,顺便说一句,更新数据源的最佳做法是分配给.data
属性,以一次全部更新所有内容,例如
source.data = new_data_dict