我正在尝试创建一个绘制多个时间序列的Bokeh应用程序,并允许用户使用CheckboxButtonGroup
小部件选择时间序列的子集。我想从python中更改显示的图形,而不是试图隐藏/取消隐藏javascript端的行。我试图通过添加多行并从回调函数更改其数据源中的值来尝试这样做。当我更改时间序列的内容或删除时间序列时,这可以正常工作,但是当我尝试向多行添加时间序列时,我在javascript端出现错误(chrome控制台打印Bokeh: Error handling message
)。
具体来说,我有一个pandas数据框,其中data
列由存储桶名称和时间戳索引:
data = pandas.DataFrame(...)
buckets = data.index.levels[0]
timestamps = data.index.levels[1]
我有一个多线图和一个控件:
plot = bokeh.plotting.Figure(x_axis_type = "datetime")
multiline = plot.multi_line(xs = [], ys = [])
bucketsControl = bokeh.models.widgets.CheckboxButtonGroup(labels = list(buckets))
我有一个更新数据源的回调函数,由控件触发:
def update(value):
xs = []
ys = []
for bucketIndex in bucketsControl.active:
bucketName = bucketsControl.labels[bucketIndex]
bucketData = data.loc[bucketName]
series = bucketData["data"]
xs.append(series.index.values)
ys.append(series.values)
multiline.data_source.data["xs"] = xs
multiline.data_source.data["ys"] = ys
bucketsControl.on_click(update)
我不确定这里是什么导致了这个问题,但是当我尝试添加另一个时间序列时,我已经看过了Bokeh服务器和网络浏览器之间的网络套接字流量,而我看到它会导致两个ModelChanged
更新:第一个更新为xs
添加另一个列表,秒数将列表添加到ys
。我怀疑BokehJS客户端无法处理第一次更新,它有一个x系列而不是y系列。
有没有办法让这个多行更新工作?或者,是否有另一种方法来更新python中的绘图结构(例如,在绘图中添加一个全新的行,而不是更改现有字形的数据源)?
答案 0 :(得分:4)
因为您更新了两次数据源。您只能通过以下方式更新一次:
data = dict(xs=xs, ys=ys)
multiline.data_source.data = data
答案 1 :(得分:0)
您可以使用patch仅更新新数据,以最小化将要发送到前端的数据
要更新整行:
source = ColumnDataSource(dict(
xs=[[1, 2, 3, 4, 5, 6]],
ys=[[1, 2, 3, 4.2, 2.2, 0.5]],
))
source.patch({
'ys' : [(0, [1, 2, 3, 4, 5, 6])]
})
要更新行片段:
source = ColumnDataSource(dict(
xs=[np.array([1, 2, 3, 4, 5, 6])],
ys=[np.array([1, 2, 3, 4.2, 2.2, 0.5])],
))
source.patch({
'ys' : [([0, slice(3, 6)], np.array([4, 5, 6]))]
})
有一种方法可以删除全部内容,因为bokeh不支持此方法
source.patch({
'ys' : [(0,[''])], # or 'ys' : [(0,numpy.array([numpy.nan]))],
})
此外,您只需在补丁字典中添加键就可以同时更新许多列