从散景中的图形中删除线

deleting line from figure in bokeh

我是 Bokeh 的新手。我制作了一个小部件,当我单击一个复选框时,我希望能够 add/delete 散景图中的一行。我有 20 个这样的复选框,我不想重新绘制整个图形,只是在未选中复选框时删除 1 行。

这是通过回调完成的,我可以在其中访问图形对象。我想有一种方法可以做这样的事情:

F=figure()
F.line('x', 'y', source=source, name='line1')
F.line('x', 'z', source=source, name='line2')

%%in callback
selected_line_name = 'line1' # this would be determined by checkbox
selected_line = F.children[selected_line_name]
delete(selected_line)

但是,我不知道如何 1) 从其父对象访问一个字形 2) 删除一个字形

我尝试设置数据源 'y'=[],但由于所有列数据源的大小必须相同,因此这会删除所有图...

有几种方法:

# Keep the glyphs in a variable:
line2 = F.line('x', 'z', source=source, name='line2')

# or get the glyph from the Figure:
line2 = F.select_one({'name': 'line2'})

# in callback:
line2.visible = False

如果将字形指定为变量并赋予名称属性,这将有助于维护共享的 'x' 数据源列。 remove 函数用 nans 填充适当的 'y' 列,restore 函数用原始值替换 nans。

这些函数需要导入 numpy 和 bokeh GlyphRenderer。考虑到简单的可见 on/off 选项,我不确定这种方法是否值得,但无论如何我都会发布它以防万一这对其他一些用例有帮助。

要删除或恢复的字形由包含在列表中的字形名称引用。

src_dict = source.data.copy()

def remove_glyphs(figure, glyph_name_list):
    renderers = figure.select(dict(type=GlyphRenderer))
    for r in renderers:
        if r.name in glyph_name_list:
            col = r.glyph.y
            r.data_source.data[col] = [np.nan] * len(r.data_source.data[col])

def restore_glyphs(figure, src_dict, glyph_name_list):
    renderers = figure.select(dict(type=GlyphRenderer))
    for r in renderers:
        if r.name in glyph_name_list:
            col = r.glyph.y
            r.data_source.data[col] = src_dict[col]

示例:

from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import Range1d, ColumnDataSource
from bokeh.models.renderers import GlyphRenderer

import numpy as np

output_notebook()

p = figure(plot_width=200, plot_height=150,
           x_range=Range1d(0, 6),
           y_range=Range1d(0, 10),
           toolbar_location=None)

source = ColumnDataSource(data=dict(x=[1, 3, 5],
                                    y1=[1, 1, 2],
                                    y2=[1, 2, 6],
                                    y3=[1, 3, 9]))

src_dict = source.data.copy()

line1 = p.line('x', 'y1',
               source=source,
               color='blue',
               name='g1',
               line_width=3)

line2 = p.line('x', 'y2',
               source=source,
               color='red',
               name='g2',
               line_width=3)

line3 = p.line('x', 'y3',
               source=source,
               color='green',
               name='g3',
               line_width=3)
print(source.data)
show(p)

输出:

{'x': [1, 3, 5], 'y1': [1, 1, 2], 'y2': [1, 2, 6], 'y3': [1, 3, 9]}

remove_glyphs(p, ['g1', 'g2'])
print(source.data)
show(p)

输出:

{'x': [1, 3, 5], 'y1': [nan, nan, nan], 'y2': [nan, nan, nan], 'y3': [1, 3, 9]}

restore_glyphs(p, src_dict, ['g1', 'g3'])
print(source.data)
show(p)

('g3'已经上图,不受影响)

输出:

{'x': [1, 3, 5], 'y1': [1, 1, 2], 'y2': [nan, nan, nan], 'y3': [1, 3, 9]}

restore_glyphs(p, src_dict, ['g2'])
print(source.data)
show(p)

输出:

{'x': [1, 3, 5], 'y1': [1, 1, 2], 'y2': [1, 2, 6], 'y3': [1, 3, 9]}