Annotations
Each annotation returns a native Altair layer, so you add it to your chart with +. They share the
base chart’s scales, so they land at the right data coordinates automatically.
Reference lines
Section titled “Reference lines”add_rule() draws horizontal (axis="y", the default) or vertical (axis="x") reference lines at
fixed values, with optional labels. strokeDash=None inherits the theme’s dashed-rule style;
strokeDash=True/False forces dashed/solid.
import dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon"])origins = ["USA", "Europe", "Japan"]
strip = ds.mark_strip(cars, "Origin", "Miles_per_Gallon", origins, yTitle="Miles per gallon")
# A labeled horizontal reference line; inherits the theme's dashed-rule style.chart = strip + ds.add_rule(30, label="30 MPG")axis="x" draws the same line vertically, at a fixed x value:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
scatter = alt.Chart(cars).mark_point().encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"),)
# axis="x" draws vertical rules; pass a list for several at once.chart = scatter + ds.add_rule(150, axis="x", label="150 hp", strokeDash=True)Pass a list of values (and a matching list of labels) for several lines in one call.
labelPosition chooses which side of the line the label sits on; labelAlign, where along it:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
scatter = alt.Chart(cars).mark_point().encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"),)
# One call places multiple reference lines (a list of values) with per-line labels.# labelPosition picks which side of the line the label sits on; labelAlign, where along it.chart = scatter + ds.add_rule( [20, 30, 40], label=["economy", "efficient", "hybrid"], labelAlign="right", labelPosition="top",)add_text() places annotations at data coordinates (numbers share the quantitative scale, strings
snap to categories) or at frame positions via nine presets (topLeft, middleCenter, …).
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
scatter = alt.Chart(cars).mark_point().encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"),)
# Position presets pin text to the chart frame; data coordinates pin it to values.chart = ( scatter + ds.add_text("n = 392", position="topRight") + ds.add_text("outlier cluster", x=200.0, y=32.0, fontSize=5))Shading
Section titled “Shading”add_shade() lays a background rectangle layer. In band mode it alternates shades across the
x-axis categories; in positions mode it shades explicit coordinate ranges.
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme(palette="blues", xLabelAngle=-45)
barley = data.barley()sites = ["Morris", "Duluth", "University Farm", "Waseca", "Crookston", "Grand Rapids"]
bar = ( alt.Chart(barley) .mark_bar() .encode( x=alt.X("site:N", sort=sites, title=None), y=alt.Y("mean(yield):Q", title="Mean yield (bu/acre)"), color=alt.Color("site:N", legend=None), ))
# Band mode: alternate background shades across the x-axis categories.chart = ds.add_shade(categories=sites, palette=[ds.colors["blues"][0], "white"], opacity=0.5) + barIn positions mode, a numeric (start, end) tuple shades a fixed range on either axis:
import dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon"])origins = ["USA", "Europe", "Japan"]
strip = ds.mark_strip(cars, "Origin", "Miles_per_Gallon", origins, yTitle="Miles per gallon")
# Positions mode: shade an explicit y-range (e.g. a reference interval).chart = ds.add_shade(palette=[ds.colors["blues"][0]], positions=[(20.0, 30.0)], axis="y", opacity=0.6) + stripWith axis="both" and a nested ((x0, x1), (y0, y1)) tuple, it shades a 2D region - an
intersection rectangle spanning both axes:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
scatter = alt.Chart(cars).mark_point().encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"),)
# axis="both" with a nested ((x_start, x_end), (y_start, y_end)) tuple shades a 2D region -# an intersection rectangle spanning both axes. Drawn under the points with +.chart = ds.add_shade(palette=[ds.colors["blues"][0]], positions=[((40, 100), (28, 48))], axis="both", opacity=0.5,) + scatterPoint labels
Section titled “Point labels”add_labels() auto-places non-overlapping text labels with connector lines for a set of points -
volcano gene labels, rank-order labels, cluster labels. Placement is deterministic (no RNG, so
figures are reproducible): each label takes the nearest clear spot, and a thin leader line runs
from each point to its label. Pass the full plotted df and let labels= select which points to
name - an integer picks that many spread evenly across the plot, a list names specific rows.
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme(chartWidth=160, chartHeight=120)
cars = ds.ensure_polars(data.cars()).drop_nulls(["Horsepower", "Miles_per_Gallon"])
scatter = alt.Chart(cars).mark_circle().encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"),)
# add_labels auto-places non-overlapping labels with connector lines. Deterministic (no RNG),# so the figure is reproducible. Pass the full df and let labels= select which points to name -# here, 8 spread evenly across the plot (farthest-point sampling, no cherry-picking).chart = scatter + ds.add_labels( cars, "Horsepower", "Miles_per_Gallon", "Name", labels=8)