链接行为#
将图表链接起来以增加图表之间的互动性通常很有用。 本节展示了一种简单的方法,使用 bokeh.plotting 接口来实现这一点。
联动平移#
通常希望在许多图表之间链接平移或缩放操作。启用此功能所需的只是在figure()调用之间共享范围对象。
from bokeh.layouts import gridplot
from bokeh.plotting import figure, show
x = list(range(21))
y0 = x
y1 = [20-xx for xx in x]
y2 = [abs(xx-10) for xx in x]
# create a new plot
s1 = figure(width=250, height=250, title=None)
s1.scatter(x, y0, size=10, color="navy", alpha=0.5)
# create a new plot and share both ranges
s2 = figure(width=250, height=250, x_range=s1.x_range, y_range=s1.y_range, title=None)
s2.scatter(x, y1, size=10, marker="triangle", color="firebrick", alpha=0.5)
# create a new plot and share only one range
s3 = figure(width=250, height=250, x_range=s1.x_range, title=None)
s3.scatter(x, y2, size=10, marker="square", color="olive", alpha=0.5)
p = gridplot([[s1, s2, s3]], toolbar_location=None)
show(p)
现在你已经学会了如何使用 bokeh.plotting 接口在多个图表之间进行联动平移。
联动刷选#
在Bokeh中,链接刷选通过在图元渲染器之间共享数据源来表达。Bokeh只需要理解对一个图元的选择必须传递给共享同一数据源的所有其他图元。要了解链接选择如何扩展到仅绘制数据源中数据子集的图元渲染器,请参阅使用过滤数据的链接选择。
以下代码展示了在两个不同的figure()调用之间进行圆形符号链接刷新的示例:
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.sampledata.penguins import data
from bokeh.transform import factor_cmap
SPECIES = sorted(data.species.unique())
TOOLS = "box_select,lasso_select,help"
source = ColumnDataSource(data)
left = figure(width=300, height=400, title=None, tools=TOOLS,
background_fill_color="#fafafa")
left.scatter("bill_length_mm", "body_mass_g", source=source,
color=factor_cmap('species', 'Category10_3', SPECIES))
right = figure(width=300, height=400, title=None, tools=TOOLS,
background_fill_color="#fafafa", y_axis_location="right")
right.scatter("bill_depth_mm", "body_mass_g", source=source,
color=factor_cmap('species', 'Category10_3', SPECIES))
show(gridplot([[left, right]]))
下面一个更复杂的示例展示了在DataTable小部件和散点图之间的链接选择:
from bokeh.layouts import column
from bokeh.models import (ColumnDataSource, DataTable, HoverTool, IntEditor,
NumberEditor, NumberFormatter, SelectEditor,
StringEditor, StringFormatter, TableColumn)
from bokeh.plotting import figure, show
from bokeh.sampledata.autompg2 import autompg2 as mpg
source = ColumnDataSource(mpg)
manufacturers = sorted(mpg["manufacturer"].unique())
models = sorted(mpg["model"].unique())
transmissions = sorted(mpg["trans"].unique())
drives = sorted(mpg["drv"].unique())
classes = sorted(mpg["class"].unique())
columns = [
TableColumn(field="manufacturer", title="Manufacturer",
editor=SelectEditor(options=manufacturers),
formatter=StringFormatter(font_style="bold")),
TableColumn(field="model", title="Model",
editor=StringEditor(completions=models)),
TableColumn(field="displ", title="Displacement",
editor=NumberEditor(step=0.1), formatter=NumberFormatter(format="0.0")),
TableColumn(field="year", title="Year", editor=IntEditor()),
TableColumn(field="cyl", title="Cylinders", editor=IntEditor()),
TableColumn(field="trans", title="Transmission",
editor=SelectEditor(options=transmissions)),
TableColumn(field="drv", title="Drive", editor=SelectEditor(options=drives)),
TableColumn(field="class", title="Class", editor=SelectEditor(options=classes)),
TableColumn(field="cty", title="City MPG", editor=IntEditor()),
TableColumn(field="hwy", title="Highway MPG", editor=IntEditor()),
]
data_table = DataTable(source=source, columns=columns, editable=True, width=800,
index_position=-1, index_header="row index", index_width=60)
p = figure(width=800, height=300, tools="pan,wheel_zoom,xbox_select,reset", active_drag="xbox_select")
cty = p.scatter(x="index", y="cty", fill_color="#396285", size=8, alpha=0.5, source=source)
hwy = p.scatter(x="index", y="hwy", fill_color="#CE603D", size=8, alpha=0.5, source=source)
tooltips = [
("Manufacturer", "@manufacturer"),
("Model", "@model"),
("Displacement", "@displ"),
("Year", "@year"),
("Cylinders", "@cyl"),
("Transmission", "@trans"),
("Drive", "@drv"),
("Class", "@class"),
]
cty_hover_tool = HoverTool(renderers=[cty], tooltips=[*tooltips, ("City MPG", "@cty")])
hwy_hover_tool = HoverTool(renderers=[hwy], tooltips=[*tooltips, ("Highway MPG", "@hwy")])
p.add_tools(cty_hover_tool, hwy_hover_tool)
show(column(p, data_table))
链接十字准线#
在图表之间链接十字准线工具是另一种可以帮助使不同图表之间的比较更容易的技术。在Bokeh中,十字准线工具可以配置为共享Span实例作为它们的覆盖层,这将导致这些十字准线被链接在一起。下面展示了这一点:
from random import random
from bokeh.layouts import row
from bokeh.models import CrosshairTool, Span
from bokeh.plotting import figure, show
x = [random() * 10 for _ in range(200)]
y = [random() * 10 for _ in range(200)]
width = Span(dimension="width", line_dash="dashed", line_width=2)
height = Span(dimension="height", line_dash="dotted", line_width=2)
p1 = figure(height=400, width=400, x_range=(0, 10), y_range=(0, 10),
tools="hover", toolbar_location=None)
p1.add_tools(CrosshairTool(overlay=[width, height]))
p1.circle(x, y, radius=0.2, alpha=0.3, hover_alpha=1.0)
p2 = figure(height=400, width=250, x_range=(0, 10), y_range=(0, 10),
tools="hover", toolbar_location=None)
p2.add_tools(CrosshairTool(overlay=[width, height]))
p2.circle(x, y, radius=0.2, alpha=0.3, hover_alpha=1.0)
show(row(p1, p2))
链接属性#
也可以使用js_link()方法将Bokeh模型属性的值链接在一起,以保持它们的同步。
下面的示例将一个圆形符号的半径链接到Slider小部件的值:
from bokeh.layouts import column
from bokeh.models import Slider
from bokeh.plotting import figure, show
plot = figure(width=400, height=400)
r = plot.circle([1,2,3,4,5], [3,2,5,6,4], radius=0.2, alpha=0.5)
slider = Slider(start=0.1, end=2, step=0.01, value=0.2)
slider.js_link('value', r.glyph, 'radius')
show(column(plot, slider))
链接是在JavaScript中完成的,因此此方法适用于独立的Bokeh文档或Bokeh服务器应用程序。
查看Widgets and DOM elements以获取有关不同小部件的更多信息,以及JavaScript callbacks以获取有关创建任意JavaScript回调的更多信息。