Bokeh如何获取GlyphRenderer进行注释

问题描述 投票:2回答:1

使用Bokeh,我如何获得Renderer(或GlyphRenderer)的Annotation?这可能吗?

我希望能够通过交互式图例打开和关闭Band(这是一个Annotation),所以我需要能够将Renderers列表传递给LegendItem构造函数。

这段代码:

maxline = fig.line(x='Date', y=stn_max, line_width=0.5, legend=stn_max, name="{}_line".format(stn_max), color=stn_color, alpha=0.75, source=source)
minline = fig.line(x='Date', y=stn_min, line_width=0.5, legend=stn_min, name="{}_line".format(stn_min), color=stn_color, alpha=0.75, source=source)
band = bkm.Band(base='Date', lower=stn_min, upper=stn_max, fill_alpha=0.50, line_width=0.5, fill_color=stn_color, source=source)
bkm.LegendItem(label=stn, renderers=[maxline, minline, band])

产生此错误

...
ValueError: expected an element of List(Instance(GlyphRenderer)), got seq with invalid items [Band(id='1091', ...)]
python plot bokeh
1个回答
2
投票

对于LegendItem,只有GlyphRenderer的实例可以传递给它的renderers属性,Band不是基于GlyphRenderer所以它给出了错误。在下面的代码中,Band可见性通过回调切换:

from bokeh.plotting import figure, show
from bokeh.models import Band, ColumnDataSource, Legend, LegendItem, CustomJS
import pandas as pd
import numpy as np

x = np.random.random(2500) * 140 - 20
y = np.random.normal(size = 2500) * 2 + 5
df = pd.DataFrame(data = dict(x = x, y = y)).sort_values(by = "x")

sem = lambda x: x.std() / np.sqrt(x.size)
df2 = df.y.rolling(window = 100).agg({"y_mean": np.mean, "y_std": np.std, "y_sem": sem})
df2 = df2.fillna(method = 'bfill')
df = pd.concat([df, df2], axis = 1)
df['lower'] = df.y_mean - df.y_std
df['upper'] = df.y_mean + df.y_std

source = ColumnDataSource(df.reset_index())
p = figure(tools = "pan,wheel_zoom,box_zoom,reset,save")
scatter = p.scatter(x = 'x', y = 'y', line_color = None, fill_alpha = 0.3, size = 5, source = source)
band = Band(base = 'x', lower = 'lower', upper = 'upper', source = source)
p.add_layout(band)
p.title.text = "Rolling Standard Deviation"
p.xaxis.axis_label = 'X'
p.yaxis.axis_label = 'Y'

callback = CustomJS(args = dict(band = band), code = """
if (band.visible == false)
    band.visible = true;
else
    band.visible = false; """)

legend = Legend(items = [ LegendItem(label = "x", renderers = [scatter, band.source.selection_policy]) ])
legend.click_policy = 'hide'
scatter.js_on_change('visible', callback)
p.add_layout(legend)
show(p)

结果:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.