注释#

Bokeh 包含几种不同的 注释 类型,您可以使用它们向可视化添加补充信息。

标题#

使用 Title 注释添加描述性文本,该文本在绘图边缘周围呈现。

如果您使用 bokeh.plotting 接口,添加基本标题的最快捷方式是将文本作为 title 参数传递给 figure()

from bokeh.plotting import figure, show

p = figure(title="Basic Title", width=300, height=300)

p.scatter([1, 2], [3, 4])

show(p)

默认标题通常位于绘图上方,左对齐。

标题文本的值可以包含换行符,这将导致多行标题。

p = figure(title="A longer title\nwith a second line underneath")

要定义标题相对于绘图的放置位置,请使用 title_location 参数。标题可以位于绘图的上方、下方、左侧或右侧。例如

from bokeh.plotting import figure, show

p = figure(title="Left Title", title_location="left",
           width=300, height=300)

p.scatter([1, 2], [3, 4])

show(p)

使用绘图的 .title 属性自定义默认 Title。使用标准 文本属性 定义视觉属性,例如字体、边框和背景。

此示例使用 .title 属性设置字体和背景属性以及标题文本和标题对齐方式

from bokeh.plotting import figure, show

p = figure(width=300, height=300)

p.scatter([1, 2], [3, 4])

# configure visual properties on a plot's title attribute
p.title.text = "Title With Options"
p.title.align = "right"
p.title.text_color = "orange"
p.title.text_font_size = "25px"
p.title.background_fill_color = "#aaaaee"

show(p)

请注意,align 属性相对于文本方向。例如:如果您将标题放置在绘图的左侧,将 align 属性设置为 "left" 表示您的文本在左下角呈现。

要向文档添加更多标题,您需要创建额外的 Title 对象。使用绘图的 add_layout() 方法将这些额外的 Title 对象包含在您的文档中

from bokeh.models import Title
from bokeh.plotting import figure, show

p = figure(title="Left Title", title_location="left",
           width=300, height=300)

p.scatter([1, 2], [3, 4])

# add extra titles with add_layout(...)
p.add_layout(Title(text="Bottom Centered Title", align="center"), "below")

show(p)

如果标题和 工具栏 被放置在绘图的同一侧,它们将占据相同空间

from bokeh.plotting import figure, show

p = figure(title="Top Title with Toolbar", toolbar_location="above",
           width=600, height=300)

p.scatter([1, 2], [3, 4])

show(p)

如果绘图大小足够大,这会导致更紧凑的绘图。但是,如果绘图大小不够大,标题和工具栏可能会在视觉上重叠。

图例#

向绘图添加图例的最简单方法是在调用 glyph 方法时包含任何 legend_labellegend_grouplegend_field 属性。Bokeh 然后会自动为您创建一个 Legend 对象。

要更高级地控制绘图的图例,请访问 Legend 对象 直接

基本图例标签#

要为 glyph 提供一个简单的显式标签,请传递 legend_label 关键字参数

p.circle('x', 'y', legend_label="some label")

如果您为多个 glyph 分配相同的标签名称,所有 glyph 将被合并到具有该标签的单个图例项中。

import numpy as np

from bokeh.plotting import figure, show

x = np.linspace(0, 4*np.pi, 100)
y = np.sin(x)

p = figure()

p.scatter(x, y, size=3, marker="square", legend_label="sin(x)", line_color="green")
p.line(x, y, legend_label="sin(x)", line_color="green")

p.line(x, 2*y, legend_label="2*sin(x)",
       line_dash=[4, 4], line_color="orange", line_width=2)

p.scatter(x, 3*y, legend_label="3*sin(x)", size=7, fill_color=None)
p.line(x, 3*y, legend_label="3*sin(x)")

show(p)

自动分组(Python 端)#

如果您的数据采用 ColumnDataSource 的形式,Bokeh 可以从 ColumnDataSource 的某个列中的字符串生成图例条目。这样,您可以根据 glyph 组创建图例条目。

要使用 ColumnDataSource 的某个列中的数据来生成绘图的图例,请将列名作为 legend_group 关键字参数传递给 glyph 方法

p.circle('x', 'y', legend_group="colname", source=source)

因为 legend_group 引用 ColumnDataSource 的某个列,所以您始终需要为 glyph 方法提供 source 参数。此外,包含标签名称的列必须在此时点出现在数据源中

from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show

orange, blue = '#ef8a62', '#67a9cf'

source = ColumnDataSource(dict(
    x=[1, 2, 3, 4, 5, 6],
    y=[2, 1, 2, 1, 2, 1],
    color=[orange, blue, orange, blue, orange, blue],
    label=['hi', 'lo', 'hi', 'lo', 'hi', 'lo'],
))

p = figure(x_range=(0, 7), y_range=(0, 3), height=300, tools='save')

# legend field matches the column in the source
p.circle('x', 'y', radius=0.5, color='color',
         legend_group='label', source=source)

show(p)

使用 legend_group 表示 Bokeh 会立即对图例条目进行分组。因此,任何后续 Python 代码都将能够在 Legend.items 属性中看到各个图例项。这样,您可以随时重新排列或修改图例。

自动分组(浏览器端)#

您还可以选择仅在 JavaScript 端(在浏览器中)对图例中的元素进行分组。如果您想对仅在 JavaScript 端计算的列进行分组,使用浏览器端分组是有意义的。

p.circle('x', 'y', legend_field="colname", source=source)

在这种情况下,Python 代码不会Legend.items 中看到多个项目。相反,只有一个项目代表分组,分组在浏览器中发生。

from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show

orange, blue = '#ef8a62', '#67a9cf'

source = ColumnDataSource(dict(
    x=[1, 2, 3, 4, 5, 6],
    y=[2, 1, 2, 1, 2, 1],
    color=[orange, blue, orange, blue, orange, blue],
    label=['hi', 'lo', 'hi', 'lo', 'hi', 'lo'],
))

p = figure(x_range=(0, 7), y_range=(0, 3), height=300, tools='save')

# legend field matches the column in the source
p.circle('x', 'y', radius=0.5, color='color',
         legend_field='label', source=source)

show(p)

隐藏图例项#

要手动控制各个图例项的可见性,请将 visible 属性设置为 LegendItemTrueFalse

import numpy as np

from bokeh.plotting import figure, show

x = np.linspace(0, 4*np.pi, 100)
y = np.cos(x)

p = figure(height=300)

# create two renderers with legend labels
p.scatter(x, y, legend_label="cox(x)")
p.line(x, 2*y, legend_label="2*cos(x)",
       line_dash=[4, 4], line_color="orange", line_width=2)

# set legend label visibility for second renderer to False
p.legend.items[1].visible = False

show(p)

注意

如果图例中的所有项目都不可见,则整个图例将被隐藏。此外,如果您使用 浏览器端自动分组 并将 legend_field 项的可见性设置为 False,则整个组将不可见。

二维图例#

要获得具有多个列或行的图例,可以设置 Legendnrowsncols 属性为正整数。如果一行没有足够的空间容纳所有图例项,这将很有用,可以避免图例被截断。行和列的定义取决于图例的 orientation

import numpy as np

from bokeh.layouts import column
from bokeh.plotting import figure, show

x = np.linspace(0, 4*np.pi, 100)
sinx = np.sin(x)

p1 = figure(title='Default legend layout', width=500, height=300)
[p1.line(x, (1 + i/20)*sinx, legend_label=f"{1+i/20:.2f}*sin(x)") for i in range(7)]

p2 = figure(title='Legend layout with 2 columns', width=500, height=300)
[p2.line(x, (1 + i/20)*sinx, legend_label=f"{1+i/20:.2f}*sin(x)") for i in range(7)]
p2.legend.ncols=2

p3 = figure(title='Legend layout with 3 rows', width=500, height=300)
[p3.line(x, (1 + i/20)*sinx, legend_label=f"{1+i/20:.2f}*sin(x)") for i in range(7)]
p3.legend.nrows=3

show(column(p1, p2, p3))

手动图例#

要手动构建图例,请不要使用任何 legend 参数,而是直接将值分配给 Legend 对象的各个属性。

要查看创建上述图形的源代码,请访问完整的 图例示例 单页。

显式索引#

要显式指定要在图例中使用的 ColumnDataSource 中的哪个索引,请设置 LegendItemindex 属性。

当您使用以多个部分呈现的 glyph 时,这对于在图例中显示多个条目很有用,例如 MultiLine (multi_line()) 或 Patches patches()

from bokeh.models import Legend, LegendItem
from bokeh.plotting import figure, show

p = figure()

r = p.multi_line([[1,2,3], [1,2,3]], [[1,3,2], [3,4,3]],
                 color=["orange", "red"], line_width=4)

legend = Legend(items=[
    LegendItem(label="orange", renderers=[r], index=0),
    LegendItem(label="red", renderers=[r], index=1),
])
p.add_layout(legend)

show(p)

交互式图例#

您可以使用图例作为交互式元素来控制绘图外观的某些方面。单击或点击交互式图例条目会控制与图例条目关联的 glyph 的可见性。

有关更多信息和示例,请参阅用户指南中的 交互式图例

注意

当前,交互式图例 的功能仅适用于上面描述的基本图例标签。通过指定列来自动分组创建的图例目前尚不支持交互式功能。

颜色条#

要创建 ColorBar,您可以传递一个包含颜色调色板的 ColorMapper 实例,例如

color_bar = ColorBar(color_mapper=color_mapper, padding=5)

但是,对于许多图形,如果您已经为图形配置了颜色映射,则可以在图形方法返回的渲染器上调用 construct_color_bar 来自动创建颜色条。

color_bar = r.construct_color_bar(padding=5)

颜色条可以位于绘图的内部、左侧、右侧、下方或上方。使用 add_layout() 方法将 ColorBar 对象添加到绘图时,指定颜色条的位置。

import numpy as np

from bokeh.models import LogColorMapper
from bokeh.plotting import figure, show


def normal2d(X, Y, sigx=1.0, sigy=1.0, mux=0.0, muy=0.0):
    z = (X-mux)**2 / sigx**2 + (Y-muy)**2 / sigy**2
    return np.exp(-z/2) / (2 * np.pi * sigx * sigy)

X, Y = np.mgrid[-3:3:200j, -2:2:200j]
Z = normal2d(X, Y, 0.1, 0.2, 1.0, 1.0) + 0.1*normal2d(X, Y, 1.0, 1.0)
image = Z * 1e6

color_mapper = LogColorMapper(palette="Viridis256", low=1, high=1e7)

plot = figure(x_range=(0,1), y_range=(0,1), toolbar_location=None)
r = plot.image(image=[image], color_mapper=color_mapper,
               dh=1.0, dw=1.0, x=0, y=0)

color_bar = r.construct_color_bar(padding=1)

plot.add_layout(color_bar, "right")

show(plot)

比例尺#

ScaleBar 是一个视觉指示器,可以让您估量绘图上特征的大小。这在使用地图或 CT 或 MRI 扫描等图像时特别有用,并且在使用轴线不合适或过于冗长的情况下也适用。

要创建 ScaleBar,用户至少需要提供一个 Range,显式或隐式。

from bokeh.models import Range1d, ScaleBar

scale_bar = ScaleBar(range=Range1d(start=0, end=1000))
plot.add_layout(scale_bar)

该范围也可以与绘图共享。

from bokeh.models import Range1d, ScaleBar

scale_bar = ScaleBar(range=plot.y_range)
plot.add_layout(scale_bar)

ScaleBar 的默认范围是 "auto",它使用与比例尺关联的绘图的默认 x 或 y 范围,具体取决于比例尺的方向 (Plot.x_range 用于 "horizontal"Plot.y_range 用于 "vertical")。

此外,用户可以提供测量单位 (ScaleBar.dimensional,它接受 Dimensional 模型的实例) 和数据范围的单位 (ScaleBar.unit)。默认测量单位是公制长度,由 MetricLength 模型表示,默认数据范围单位是米 ("m"),与默认测量系统的基本单位相同。

如果数据范围的单位与基本单位不同,则用户可以通过适当更改 ScaleBar.unit 来指示这一点。例如,如果范围以公里为单位,则用户会使用以下方式指示这一点:

from bokeh.models import ScaleBar, Metric

scale_bar = ScaleBar(
    range=plot.y_range,
    unit="km",
)
plot.add_layout(scale_bar)

可以通过配置 ScaleBar.dimensional 属性来提供其他测量单位。这可能是其他预定义的测量单位,如英制长度 (ImperialLength) 或角度单位 (Angular)。用户还可以定义自定义测量单位。例如,要定义自定义公制单位(例如,对于涉及电子伏特 (eV) 的绘图),用户可以使用 Metric(base_unit="eV") 作为基础

from bokeh.models import ScaleBar, Metric

scale_bar = ScaleBar(
    range=plot.y_range,
    unit="MeV",
    dimensional=Metric(base_unit="eV"),
)
plot.add_layout(scale_bar)

非公制测量单位可以使用 CustomDimensional 模型构建。例如,角度测量单位可以按以下方式定义:

from bokeh.models import ScaleBar
from bokeh.models.annotations.dimensional import CustomDimensional

units = CustomDimensional(
    basis={
        "°":  (1,      "^\\circ",           "degree"),
        "'":  (1/60,   "^\\prime",          "minute"),
        "''": (1/3600, "^{\\prime\\prime}", "second"),
    }
    ticks=[1, 3, 6, 12, 60, 120, 240, 360]
)

scale_bar = ScaleBar(
    range=plot.y_range,
    unit="''",
    dimensional=units,
)
plot.add_layout(scale_bar)

带有自定义测量单位的比例尺的完整示例:

import numpy as np

from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Metric, RangeTool, ScaleBar
from bokeh.plotting import figure, show

n_points = 3000
x_values = np.linspace(0, 100, n_points)
y_values = np.random.randn(n_points).cumsum()

source = ColumnDataSource(data=dict(x=x_values, y=y_values))

detailed_plot = figure(
    width=800,
    height=300,
    tools=["xpan", "xzoom_in", "xzoom_out", "reset", "wheel_zoom"],
    toolbar_location="above",
    active_scroll="wheel_zoom",
    background_fill_color="#efefef",
    x_range=(22, 30),
    y_axis_location=None,
)

detailed_plot.line("x", "y", source=source)

scale_bar = ScaleBar(
    range=detailed_plot.y_range,
    unit="MeV",
    dimensional=Metric(base_unit="eV"),
    orientation="vertical",
    location="top_left",
    background_fill_color=None,
    border_line_color=None,
)
detailed_plot.add_layout(scale_bar)

select_plot = figure(
    width=detailed_plot.width,
    height=150,
    y_range=detailed_plot.y_range,
    y_axis_location=None,
    tools="",
    toolbar_location=None,
    background_fill_color=detailed_plot.background_fill_color,
)

select_plot.line("x", "y", source=source)
select_plot.x_range.range_padding = 0
select_plot.ygrid.grid_line_color = None

range_tool = RangeTool(x_range=detailed_plot.x_range)
range_tool.overlay.fill_color = "navy"
range_tool.overlay.fill_alpha = 0.2
select_plot.add_tools(range_tool)

show(column(detailed_plot, select_plot))

箭头#

您可以使用 Arrow 注释连接图形和标签注释。箭头还可以帮助突出显示绘图区域。

箭头是复合注释。这意味着它们使用额外的 ArrowHead 对象作为它们的 startend。默认情况下,Arrow 注释是一个单边箭头:end 属性设置为 OpenHead 类型箭头(看起来像一个开放式楔形风格),start 属性设置为 None。如果您想创建双边箭头,请将 startend 属性都设置为可用箭头之一。

可用的箭头有:

使用以下属性控制箭头的外观:

  • 使用 size 属性来控制任何箭头的尺寸。

  • 使用标准的 线条属性(如 line_colorline_alpha)来控制箭头轮廓的外观。

  • 使用 fill_colorfill_alpha 来控制箭头内表面的外观(如果适用)。

Arrow 对象本身具有标准的 线条属性。设置这些属性来控制箭头轴的颜色和外观。例如:

my_arrow.line_color = "blue"
my_arrow.line_alpha = 0.6

可选地,您可以设置 x_rangey_range 属性,使箭头注释引用额外的非默认 x 或 y 范围。这与 双轴 的工作方式相同。

from bokeh.models import Arrow, NormalHead, OpenHead, VeeHead
from bokeh.palettes import Muted3 as color
from bokeh.plotting import figure, show

p = figure(tools="", toolbar_location=None, background_fill_color="#efefef")
p.grid.grid_line_color = None

p.circle(x=(0, 1, 0.5), y=(0, 0, 0.7), radius=0.1, color="#fafafa")

vh = VeeHead(size=35, fill_color=color[0])
p.add_layout(Arrow(end=vh, x_start=0.5, y_start=0.7, x_end=0, y_end=0))

nh = NormalHead(fill_color=color[1], fill_alpha=0.5, line_color=color[1])
p.add_layout(Arrow(end=nh, line_color=color[1], line_dash=[15, 5],
                   x_start=1, y_start=0, x_end=0.5, y_end=0.7))

oh = OpenHead(line_color=color[2], line_width=5)
p.add_layout(Arrow(end=oh, line_color=color[2], line_width=5,
                   x_start=0, y_start=0, x_end=1, y_end=0))

show(p)

#

Band 注释是与绘图中数据在维度上相关联的彩色条带。带注释的常见用途之一是指示与一系列测量相关的误差。

要定义一个带,可以使用 屏幕单位数据单位

import numpy as np
import pandas as pd

from bokeh.models import Band, ColumnDataSource
from bokeh.plotting import figure, show

# Create some random data
x = np.random.random(2500) * 140 +20
y = np.random.normal(size=2500) * 2 + 6 * np.log(x)

df = pd.DataFrame(data=dict(x=x, y=y)).sort_values(by="x")

df2 = df.y.rolling(window=300).agg({"y_mean": "mean", "y_std": "std"})

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="", toolbar_location=None, x_range=(40, 160))
p.title.text = "Rolling Standard Deviation"
p.xgrid.grid_line_color=None
p.ygrid.grid_line_alpha=0.5

p.scatter(x="x", y="y", color="blue", marker="dot", size=10, alpha=0.4, source=source)

p.line("x", "y_mean", line_dash=(10, 7), line_width=2, source=source)

band = Band(base="x", lower="lower", upper="upper", source=source,
            fill_alpha=0.3, fill_color="yellow", line_color="black")
p.add_layout(band)

show(p)

方框注释#

BoxAnnotation 是一个矩形框,您可以使用它来突出显示特定的绘图区域。使用 屏幕单位数据单位 来定位方框注释。

要定义这些框的边界,请使用 left/righttop/ bottom 属性。如果您只提供一个边界(例如,left 值,但没有 right 值),则该框将扩展到未指定维度的可用绘图区域的边缘。

from bokeh.models import BoxAnnotation
from bokeh.plotting import figure, show
from bokeh.sampledata.glucose import data

TOOLS = "pan,wheel_zoom,box_zoom,reset,save"

#reduce data size
data = data.loc['2010-10-06':'2010-10-13'].reset_index()

p = figure(x_axis_type="datetime", tools=TOOLS)

p.line("datetime", "glucose", source=data, color="gray", legend_label="glucose")

low_box = BoxAnnotation(top=80, fill_alpha=0.2, fill_color='#D55E00')
mid_box = BoxAnnotation(bottom=80, top=180, fill_alpha=0.2, fill_color='#0072B2')
high_box = BoxAnnotation(bottom=180, fill_alpha=0.2, fill_color='#D55E00')

p.add_layout(low_box)
p.add_layout(mid_box)
p.add_layout(high_box)

p.title.text = "Glucose Range"
p.xgrid.grid_line_color=None
p.ygrid.grid_line_alpha=0.5
p.xaxis.axis_label = 'Time'
p.yaxis.axis_label = 'Value'
p.legend.level = "overlay"
p.legend.location = "top_left"

show(p)

多边形注释#

PolyAnnotation 是一个多边形,其顶点位于 屏幕单位数据单位 中。

要定义多边形的顶点,请向 xsys 属性提供一系列坐标。Bokeh 会自动将最后一个顶点连接到第一个顶点,以创建一个封闭的形状。

from datetime import datetime as dt

import pandas as pd

from bokeh.models import PolyAnnotation
from bokeh.plotting import figure, show
from bokeh.sampledata.stocks import GOOG

p = figure(height=200, x_axis_type="datetime",
           background_fill_color="#efefef", title="Google stock")

df = pd.DataFrame(GOOG)
df["date"] = pd.to_datetime(df["date"])

p.line(df["date"], df["close"], line_width=1.5, color="grey")

start_date = dt(2008, 11, 24)
start_y = df.loc[df["date"] == start_date]["close"].values[0]

end_date = dt(2010, 1, 4)
end_y = df.loc[df["date"] == end_date]["close"].values[0]

polygon = PolyAnnotation(
    fill_color="blue", fill_alpha=0.2,
    xs=[start_date, start_date, end_date, end_date],
    ys=[start_y - 100, start_y + 100, end_y + 100, end_y - 100],
)
p.add_layout(polygon)

show(p)

标签#

标签是包含有关图形或绘图区域的附加信息的矩形框。

要创建单个文本标签,请使用 Label 注释。以下是此注释最重要的属性

  • 一个包含要显示在标签内的文本的 text 属性。

  • xy 属性用于设置位置(以 屏幕单位数据单位 表示)。

  • x_offsety_offset 属性用于指定标签相对于其 xy 坐标的位置。

  • 标准的 文本属性 以及其他样式参数,例如

  • border_linebackground_fill 属性。

Label(x=100, y=5, x_units='screen', text='Some Stuff',
      border_line_color='black', border_line_alpha=1.0,
      background_fill_color='white', background_fill_alpha=1.0)

text 值可以包含换行符,这将导致多行标签。

Label(x=100, y=5, text='A very long label\nwith mutiple lines')

要一次创建多个标签,请使用 LabelSet 注解。要配置标签集的标签,请使用包含标签属性数据(例如 textxy)的列的数据源。如果您直接为 x_offsety_offset 等属性分配值,而不是列名,则此值将用于标签集的所有标签。

LabelSet(x='x', y='y', text='names',
         x_offset=5, y_offset=5, source=source)

以下示例说明了 LabelLabelSet 的用法

from bokeh.models import ColumnDataSource, Label, Node
from bokeh.plotting import figure, show

source = ColumnDataSource(data=dict(
    height=[66, 71, 72, 68, 58, 62],
    weight=[165, 189, 220, 141, 260, 174],
    names=["Mark", "Amir", "Matt", "Greg", "Owen", "Juan"],
))

p = figure(title="Dist. of 10th Grade Students", x_range=(140, 275))
p.xaxis.axis_label = "Weight (lbs)"
p.yaxis.axis_label = "Height (in)"

p.scatter(x="weight", y="height", size=8, source=source)

p.text(x="weight", y="height", text="names",
       x_offset=5, y_offset=5, anchor="bottom_left", source=source)

frame_left = Node(target="frame", symbol="left", offset=5)
frame_bottom = Node(target="frame", symbol="bottom", offset=-5)

citation = Label(
    x=frame_left,
    y=frame_bottom,
    anchor="bottom_left",
    text="Collected by Luke C. 2016-04-01",
    padding=10,
    border_radius=5,
    border_line_color="black", background_fill_color="white",
)

p.add_layout(citation)

show(p)

LabelSettext 值可以包含换行符,这将导致多行标签。

斜率#

Slope 注解是从图表的边缘到另一个边缘以特定角度延伸的线条。

以下是此注解最常用的属性

import numpy as np

from bokeh.models import Slope
from bokeh.palettes import Sunset10
from bokeh.plotting import figure, show

# linear equation parameters
slope, intercept = 2, 10

x = np.arange(0, 20, 0.2)
y = slope * x + intercept + np.random.normal(0, 4, 100)

blue, yellow = Sunset10[0], Sunset10[5]

p = figure(width=600, height=600, x_axis_label='x', y_axis_label='y',
           background_fill_color="#fafafa")
p.y_range.start = 0

p.scatter(x, y, size=8, alpha=0.8, fill_color=yellow, line_color="black")

slope = Slope(gradient=slope, y_intercept=intercept,
              line_color=blue, line_dash='dashed', line_width=4)

p.add_layout(slope)

show(p)

跨度#

Span 注解是垂直于图表 x 轴或 y 轴的线条。它们只有一个维度(宽度或高度),并且从图表的边缘延伸到相对的边缘。

以下是此注解最常用的属性

  • dimension:跨度线的方向。方向可以是以下两个值之一:* "height" 用于平行于图表 x 轴的线条。或 "width" 用于平行于图表 y 轴的线条。

  • location:跨度在使用 dimension 指定的轴上的位置。

  • location_unitslocation 属性的 单位 类型。默认情况下使用 数据单位

  • 标准的 线属性

from datetime import datetime as dt

from bokeh.models import Span
from bokeh.plotting import figure, show
from bokeh.sampledata.daylight import daylight_warsaw_2013

p = figure(height=350, x_axis_type="datetime", y_axis_type="datetime",
           title="2013 Sunrise and Sunset in Warsaw with DST dates marked",
           y_axis_label="Time of Day", background_fill_color="#fafafa")
p.y_range.start = 0
p.y_range.end = 24 * 60 * 60 * 1000

p.line("Date", "Sunset", source=daylight_warsaw_2013,
       color='navy', line_dash="dotted", line_width=2, legend_label="Sunset")
p.line("Date", "Sunrise", source=daylight_warsaw_2013,
       color='orange', line_dash="dashed", line_width=2, legend_label="Sunrise")

dst_start = Span(location=dt(2013, 3, 31, 2, 0, 0), dimension='height',
                 line_color='#009E73', line_width=5)
p.add_layout(dst_start)

dst_end = Span(location=dt(2013, 10, 27, 3, 0, 0), dimension='height',
               line_color='#009E73', line_width=5)
p.add_layout(dst_end)

p.yaxis.formatter.days = "%Hh"
p.xgrid.grid_line_color = None

show(p)

须线#

Whisker 注解是尺寸上与图表中的数据相关的“茎”。您可以使用 数据单位屏幕单位 来定义此注解。

须线注解的常见用法是指示单个点处测量的误差范围或不确定性。

以下是此注解最常用的属性

  • lower:须线末端的坐标。

  • upper:须线末端的坐标。

  • dimension:须线的方向。方向可以是以下两个值之一:* "width" 用于平行于图表 x 轴的须线。或 "height" 用于平行于图表 y 轴的须线。

  • base:须线在使用 dimension 指定的维度上的位置。

  • 标准的 线属性

from bokeh.models import ColumnDataSource, Whisker
from bokeh.plotting import figure, show
from bokeh.sampledata.autompg2 import autompg2 as df
from bokeh.transform import factor_cmap, jitter

classes = list(sorted(df["class"].unique()))

p = figure(height=400, x_range=classes, background_fill_color="#efefef",
           title="Car class vs HWY mpg with quantile ranges")
p.xgrid.grid_line_color = None

g = df.groupby("class")
upper = g.hwy.quantile(0.80)
lower = g.hwy.quantile(0.20)
source = ColumnDataSource(data=dict(base=classes, upper=upper, lower=lower))

error = Whisker(base="base", upper="upper", lower="lower", source=source,
                level="annotation", line_width=2)
error.upper_head.size=20
error.lower_head.size=20
p.add_layout(error)

p.scatter(jitter("class", 0.3, range=p.x_range), "hwy", source=df,
          alpha=0.5, size=13, line_color="white",
          color=factor_cmap("class", "Light7", classes))

show(p)