如何更新多行字形的 ColumnDataSource 数据?

How to update a ColumnDataSource data for a MultiLine glyph?

我正在尝试创建一个绘制多个时间序列的 Bokeh 应用程序,并允许用户使用 CheckboxButtonGroup 小部件 select 时间序列的子集。我想从 python 更改显示的图形,而不是尝试在 javascript 侧更改 hide/un-hide 行。我试图通过添加多行并从回调函数更改其数据源中的值来做到这一点。这在我更改时间序列的内容或删除时间序列时工作正常,但一旦我尝试将时间序列添加到多行,我就会在 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 更新绘图的结构(例如,向绘图添加一个全新的行,而不是更改现有字形的数据源)?

因为你更新了两次数据源。您只能通过以下方式更新一次:

data = dict(xs=xs, ys=ys)
multiline.data_source.data = data

您可以使用 patch 仅更新新数据,最大限度地减少将要发送到 front-end

的数据
  • 要更新整行:

    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]))]
    })
    
  • 有一个 hacky 方法可以删除整体,因为 bokeh 不支持这种方法

    source.patch({
        'ys' : [(0,[''])],     # or 'ys' : [(0,numpy.array([numpy.nan]))], 
    })
    

此外,您可以同时更新许多列,只需将键添加到补丁字典