Annotations¶
Überblick¶
Wir können visuelle Hinweise (Begrenzungslinien, schattierte Bereiche, Beschriftungen und Pfeile usw.) zu unseren Plots hinzufügen, um bestimmte Merkmale hervorzuheben. Bokeh bietet hierfür mehrere Annotationstypen. Um Annotations hinzuzufügen, erstellen wir normalerweise ein Low-Level-Objekt und fügen es mit add_layout
unserem Diagramm hinzu. Schauen wir uns einige konkrete Beispiele an:
Spans¶
Spans sind vertikale oder horizontale Linien, für die die Spannweiten zwischen den Bemaßung angegeben werden kann, z.B.:
[1]:
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
output_notebook()
[2]:
import numpy as np
from bokeh.models.annotations import Span
x = np.linspace(0, 20, 200)
y = np.sin(x)
p = figure(y_range=(-2, 2))
p.line(x, y)
upper = Span(location=1, dimension="width", line_color="olive", line_width=4)
p.add_layout(upper)
lower = Span(
location=-1, dimension="width", line_color="firebrick", line_width=4
)
p.add_layout(lower)
show(p)
Box Annotations¶
Soll ein Bereich eines Diagramms hervorgehoben werden, so können diese mit BoxAnnotation
, den Koordinateneigenschaften
top
left
bottom
right
sowie Linien- und Fülleigenschaften das Erscheinungsbild konfiguriert werden.
Infinite Boxen können erstellt werden, indem die Koordinaten nicht angegeben werden. Wenn zum Beispiel top
nicht angegeben ist, wird die Box immer bis zum oberen Rand des Plotbereichs angezeigt, unabhängig davon, ob ein Verschieben oder Zoomen stattfindet, z.B.:
[3]:
import numpy as np
from bokeh.models.annotations import BoxAnnotation
x = np.linspace(0, 20, 200)
y = np.sin(x)
p = figure(y_range=(-2, 2))
p.line(x, y)
# region that always fills the top of the plot
upper = BoxAnnotation(bottom=1, fill_alpha=0.1, fill_color="olive")
p.add_layout(upper)
# region that always fills the bottom of the plot
lower = BoxAnnotation(top=-1, fill_alpha=0.1, fill_color="firebrick")
p.add_layout(lower)
# a finite region
center = BoxAnnotation(
top=0.6, bottom=-0.3, left=7, right=12, fill_alpha=0.1, fill_color="navy"
)
p.add_layout(center)
show(p)
Label¶
Mit der Annotation Label
können wir einzelne Beschriftungen einfach an Plots anbringen. Die anzuzeigende Position und der Text sind als x
, y
und text
konfiguriert:
Label(x=10, y=5, text="Some Label")
Standardmäßig befinden sich die Einheiten im data space, aber x_units
und y_units
können auf screen
gesetzt werden, um die Beschriftung relativ zur Zeichenfläche zu positionieren, und Labels können mit x_offset
und y_offset
positioniert werden.
Label
-Objekte haben auch Standardtext-, Zeilen- (border_line
) und Fülleigenschaften (background_fill
). Die Linien- und Fülleigenschaften gelten für einen Begrenzungsrahmen um den Text:
Label(x=10, y=5, text="Some Label", text_font_size="12pt",
border_line_color="red", background_fill_color="blue")
[4]:
from bokeh.models.annotations import Label
from bokeh.plotting import figure
p = figure(x_range=(0,10), y_range=(0,10))
p.circle([2, 5, 8], [4, 7, 6], color="olive", size=10)
label = Label(x=5, y=7, x_offset=12, text="Second Point", text_baseline="middle")
p.add_layout(label)
show(p)
LabelSet¶
Mit der Annotation LabelSet
könnt ihr viele Beschriftungen gleichzeitig erstellen, z.B. wenn ihr einen ganzen Satz von Scatter Markers beschriften möchtet. Sie ähneln Label
, können aber auch eine ColumnDataSource
als source
-Eigenschaft nutzen, wobei sich x
und y
auf Spalten in der Datenquelle beziehen.
[5]:
from bokeh.models import ColumnDataSource, LabelSet
from bokeh.plotting import figure
source = ColumnDataSource(
data=dict(
temp=[166, 171, 172, 168, 174, 162],
pressure=[165, 189, 220, 141, 260, 174],
names=["A", "B", "C", "D", "E", "F"],
)
)
p = figure(x_range=(160, 175))
p.scatter(x="temp", y="pressure", size=8, source=source)
p.xaxis.axis_label = "Temperature (C)"
p.yaxis.axis_label = "Pressure (lbs)"
labels = LabelSet(
x="temp",
y="pressure",
text="names",
level="glyph",
x_offset=5,
y_offset=5,
source=source,
)
p.add_layout(labels)
show(p)
Arrows¶
Mit der Annotation Arrow
könnt ihr auf verschiedene Elemente in eurer Zeichnung zeigen. Dies kann besonders bei Beschriftungen hilfreich sein.
So könnt ihr beispielsweise einen Pfeil erstellen, der von (0,0)
bis (1,1)
zeigt:
p.add_layout(Arrow(x_start=0, y_start=0, x_end=1, y_end=0))
Dieser Pfeil hat die Standardspitze OpenHead. Andere Arten von Pfeilspitzen sind NormalHead und VeeHead. Der Typ des Pfeilkopfs kann durch die Eigenschaften start
and end
von
Arrow
-Objekten konfiguriert werden:
p.add_layout(Arrow(start=OpenHead(), end=VeeHead(),
x_start=0, y_start=0, x_end=1, y_end=0))
Dies erzeugt einen Doppelpfeil mit OpenHead
und VeeHead
. Pfeilspitzen haben darüberhinaus den Standardsatz von Linien- und Fülleigenschaften, um deren Aussehen zu konfigurieren, z.B.:
OpenHead(line_color="firebrick", line_width=4)
Der Code und das Diagramm unten zeigen mehrere dieser Konfigurationen zusammen.
[6]:
from bokeh.models.annotations import Arrow
from bokeh.models.arrow_heads import NormalHead, OpenHead, VeeHead
p = figure(plot_width=600, plot_height=600)
p.circle(
x=[0, 1, 0.5],
y=[0, 0, 0.7],
radius=0.1,
color=["navy", "yellow", "red"],
fill_alpha=0.1,
)
p.add_layout(
Arrow(
end=OpenHead(line_color="firebrick", line_width=4),
x_start=0,
y_start=0,
x_end=1,
y_end=0,
)
)
p.add_layout(
Arrow(
end=NormalHead(fill_color="orange"),
x_start=1,
y_start=0,
x_end=0.5,
y_end=0.7,
)
)
p.add_layout(
Arrow(
end=VeeHead(size=35),
line_color="red",
x_start=0.5,
y_start=0.7,
x_end=0,
y_end=0,
)
)
show(p)
Legenden¶
Wenn Diagramme mehrere Glyphen enthalten, ist es wünschenswert, eine Legende hinzuzufügen, um Betrachtern die Interpretation zu erleichtern. Bokeh kann Legenden anhand der hinzugefügten Glyphen leicht generieren.
Einfache Legenden¶
Im einfachsten Fall könnt ihr einen String als legend
an eine Glyph-Funktion übergeben:
p.circle(x, y, legend="sin(x)")
In diesem Fall erstellt Bokeh automatisch eine Legende, die eine Darstellung dieser Glyphe zeigt.
[7]:
import numpy as np
x = np.linspace(0, 4 * np.pi, 100)
y = np.sin(x)
p = figure(height=400)
p.circle(x, y, legend_label="sin(x)")
p.line(
x,
2 * y,
legend_label="2*sin(x)",
line_dash=[4, 4],
line_color="orange",
line_width=2,
)
show(p)
Zusammengesetzte Legenden¶
Im obigen Beispiel haben wir für jede Glyphenmethode ein anderes Etikett bereitgestellt. Manchmal werden zwei (oder mehr) verschiedene Glyphen mit einer einzigen Datenquelle verwendet. In diesem Fall können zusammengesetzte Legenden erstellt werden. Wenn ihr z.B. eine Sinuskurve mit einer Linie und einer Markierung plottet, könnt ihr ihnen dieselbe Bezeichnung geben um sie dazu zu bringen, gemeinsam in der Legende zu erscheinen:
p.circle(x, y, legend="sin(x)")
p.line(x, y, legend="sin(x)", line_dash=[4, 4], line_color="orange", line_width=2)
Farbbalken¶
Farbbalken sind besonders nützlich, wenn wir die Farbe einer Glyphe entsprechend der Farbzuordnung variiert. Bokeh-Farbbalken werden mit einer Farbzuordnung konfiguriert und mit der `add_layout‘-Methode zu Plots hinzugefügt:
color_mapper = LinearColorMapper(palette="Viridis256", low=data_low, high=data_high)
color_bar = ColorBar(color_mapper=color_mapper, location=(0,0))
p.add_layout(color_bar, 'right')
Im folgenden Beispiel wird die Farbzuordnung auch zur Umwandlung der Glyphenfarbe verwendet.
[8]:
from bokeh.models import ColorBar, LinearColorMapper
from bokeh.sampledata.autompg import autompg
from bokeh.transform import transform
source = ColumnDataSource(autompg)
color_mapper = LinearColorMapper(
palette="Viridis256", low=autompg.weight.min(), high=autompg.weight.max()
)
p = figure(
x_axis_label="Horsepower",
y_axis_label="MPG",
tools="",
toolbar_location=None,
)
p.circle(
x="hp",
y="mpg",
color=transform("weight", color_mapper),
size=20,
alpha=0.6,
source=autompg,
)
color_bar = ColorBar(
color_mapper=color_mapper,
label_standoff=12,
location=(0, 0),
title="Weight",
)
p.add_layout(color_bar, "right")
show(p)