注释#
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_label、legend_group 或 legend_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
属性设置为 LegendItem
的 True
或 False
。
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
,则整个组将不可见。
二维图例#
要获得具有多个列或行的图例,可以设置 Legend
的 nrows
或 ncols
属性为正整数。如果一行没有足够的空间容纳所有图例项,这将很有用,可以避免图例被截断。行和列的定义取决于图例的 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 中的哪个索引,请设置 LegendItem
的 index
属性。
当您使用以多个部分呈现的 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
对象作为它们的 start
和 end
。默认情况下,Arrow
注释是一个单边箭头:end
属性设置为 OpenHead
类型箭头(看起来像一个开放式楔形风格),start
属性设置为 None
。如果您想创建双边箭头,请将 start
和 end
属性都设置为可用箭头之一。
可用的箭头有:
使用以下属性控制箭头的外观:
使用
size
属性来控制任何箭头的尺寸。使用标准的 线条属性(如
line_color
和line_alpha
)来控制箭头轮廓的外观。使用
fill_color
和fill_alpha
来控制箭头内表面的外观(如果适用)。
Arrow
对象本身具有标准的 线条属性。设置这些属性来控制箭头轴的颜色和外观。例如:
my_arrow.line_color = "blue"
my_arrow.line_alpha = 0.6
可选地,您可以设置 x_range
和 y_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
/right
或 top
/ 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
是一个多边形,其顶点位于 屏幕单位 或 数据单位 中。
要定义多边形的顶点,请向 xs
和 ys
属性提供一系列坐标。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
属性。x_offset
和y_offset
属性用于指定标签相对于其x
和y
坐标的位置。标准的 文本属性 以及其他样式参数,例如
border_line
和background_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
注解。要配置标签集的标签,请使用包含标签属性数据(例如 text
、x
和 y
)的列的数据源。如果您直接为 x_offset
和 y_offset
等属性分配值,而不是列名,则此值将用于标签集的所有标签。
LabelSet(x='x', y='y', text='names',
x_offset=5, y_offset=5, source=source)
以下示例说明了 Label
和 LabelSet
的用法
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)
LabelSet
的 text
值可以包含换行符,这将导致多行标签。
斜率#
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
指定的轴上的位置。标准的 线属性。
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)