Altair Composition & Layouts

Altair charts are objects β€” combine them with operators or explicit functions.

🧱 Layering β€” overlay charts on the same axes

line = alt.Chart(df).mark_line().encode(x="date:T", y="value:Q")
points = alt.Chart(df).mark_point().encode(x="date:T", y="value:Q")
 
line + points                    # shorthand operator
alt.layer(line, points)             # equivalent, explicit form

Layered charts must share compatible encodings (same x/y fields) β€” Altair merges them onto one shared axes.

Common layer pattern: trend line + rule (e.g. average line)

bars = alt.Chart(df).mark_bar().encode(x="category:N", y="value:Q")
rule = alt.Chart(df).mark_rule(color="red").encode(y="mean(value):Q")
 
bars + rule

πŸ”³ Faceting β€” small multiples, one chart type repeated per category

alt.Chart(df).mark_point().encode(
    x="a:Q", y="b:Q"
).facet(column="category:N")
 
alt.Chart(df).mark_point().encode(
    x="a:Q", y="b:Q"
).facet(row="group:N", column="category:N")
alt.Chart(df).mark_point().encode(
    x="a:Q", y="b:Q",
    column="category:N"      # shorthand, same effect as .facet(column=...) for simple cases
)

↔️ hconcat / vconcat β€” side by side, different chart types

chart1 = alt.Chart(df).mark_bar().encode(x="a", y="b")
chart2 = alt.Chart(df).mark_line().encode(x="c", y="d")
 
chart1 | chart2         # horizontal, shorthand for alt.hconcat(chart1, chart2)
chart1 & chart2            # vertical, shorthand for alt.vconcat(chart1, chart2)

Use facet when it's the SAME chart repeated per category. Use hconcat/vconcat when the charts are genuinely different (different marks, different data, unrelated axes).

Mixed grid

(chart1 | chart2) & chart3      # 2 charts on top, 1 below spanning both

πŸ” repeat β€” same chart spec across multiple fields

alt.Chart(df).mark_point().encode(
    x=alt.X(alt.repeat("column"), type="quantitative"),
    y=alt.Y(alt.repeat("row"), type="quantitative")
).properties(width=150, height=150).repeat(
    row=["a", "b", "c"],
    column=["a", "b", "c"]
)

This is Altair's equivalent to a Seaborn pairplot β€” a scatterplot matrix built via repeat() rather than a dedicated function.

🎯 Interactive selections across composed charts

brush = alt.selection_interval()
 
scatter = alt.Chart(df).mark_point().encode(
    x="a", y="b",
    color=alt.condition(brush, "category:N", alt.value("gray"))
).add_params(brush)
 
hist = alt.Chart(df).mark_bar().encode(
    x="category:N", y="count():Q"
).transform_filter(brush)
 
scatter & hist      # stacked, linked via the shared brush param

See Altair Interactivity for the full selection mechanics.

πŸ”— Next

Altair Styling & Themes Β· Altair Saving & Exporting