在多个散景图中共享交互式模型

时间:2018-07-31 09:50:44

标签: python bokeh

我只是从bokeh开始,我想在一个网格中表示3个不同地块上的3个数据集,以使它们全部都有一些可切换的垂直线。例如

x = np.arange(50)
data = np.random.rand(3, x.shape[0]) * [[0.1], [1], [100]]  # Different scales

tags = [1, 17, 31]
colors = 'red green red'.split()

ax = figure(plot_width=300, plot_height=300)
bx = figure(x_range=ax.x_range, plot_width=300, plot_height=300)
cx = figure(x_range=ax.x_range, plot_width=300, plot_height=300)

for t, c in zip(tags, colors):
    ax.add_layout(Span(location=t, dimension='height', line_color=c))
    bx.add_layout(Span(location=t, dimension='height', line_color=c))
    cx.add_layout(Span(location=t, dimension='height', line_color=c))

ax.line(x, data[0])
bx.line(x, data[1])
cx.line(x, data[2])

p = gridplot([[ax, bx, cx]])
show(p)

除了我想将Span元素添加到单个轴并使其共享这一事实之外,我想为{{ 1}}对象,并使其可以按颜色切换。

因此,在这种情况下,我将在所有3个图中共享一个图例,在这个图例中,我将有2个条目,一个用于红线,一个用于绿线。单击一种颜色会在所有绘图中隐藏该颜色的所有线条。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

由于Span没有图例属性,因此需要创建两条虚拟线以显示图例。在下面的示例中,我使用tags属性来使Span对象显示/隐藏。

import numpy as np
from bokeh.plotting import figure
from bokeh.layouts import gridplot
from bokeh.models import Span, CustomJS
from bokeh.io import output_notebook, show

x = np.arange(50)
data = np.random.rand(3, x.shape[0]) * [[0.1], [1], [100]]  # Different scales

tags = [1, 17, 31]
colors = 'red green red'.split()

ax = figure(plot_width=300, plot_height=300)
bx = figure(x_range=ax.x_range, plot_width=300, plot_height=300)
cx = figure(x_range=ax.x_range, plot_width=300, plot_height=300)

spans = {"red":[], "green":[]}

for t, c in zip(tags, colors):
    span1 = Span(location=t, dimension='height', line_color=c)
    span2 = Span(location=t, dimension='height', line_color=c)
    span3 = Span(location=t, dimension='height', line_color=c)
    ax.add_layout(span1)
    bx.add_layout(span2)
    cx.add_layout(span3)
    spans[c].extend([span1, span2, span3])

ax.line(x, data[0])
bx.line(x, data[1])
cx.line(x, data[2])

p = gridplot([[ax, bx, cx]])

red_line = ax.line([0], [0], legend="red", color="red")
green_line = ax.line([0], [0], legend="green", color="green")

ax.legend.location = "top_left"
ax.legend.click_policy="hide"

red_line.tags = spans["red"]
green_line.tags = spans["green"]

def toggle_visible(p=p):
    for line in cb_obj.tags:
        line.visible = cb_obj.visible

callback = CustomJS.from_py_func(toggle_visible)
for line in (red_line, green_line):
    line.js_on_change("visible", callback)

show(p)