position-stack

Stack position adjustment: cumulate y per x bucket.

Since 0.0.1.

Stacking is per x bucket across all groups. Rows are sorted by the grouping aesthetic so the first alphabetic level sits at the top of the bar in cartesian coords (legend top entry = top band). Under any coord-radial the cumulation flips so the first alphabetic level becomes the first slice clockwise from 12 o’clock.

Typically set on a layer as position: "stack" rather than constructed directly; construct it to pick a streamgraph offset.

Usage

position-stack(
  offset: "none",
)

Parameters

Parameter Default Description
offset "none" Baseline offset per x bucket. "none" (default) stacks from zero. "silhouette" centres each stack on zero (ThemeRiver). "wiggle" places each stack at the Byron-Wattenberg baseline that minimises the weighted wiggle of the layer boundaries, the classic streamgraph look. Both shifted offsets suit geom-area over a continuous x; neither is supported under coord-radial.

Returns

Position dictionary with name: "stack", consumed by plot.

Examples

Two groups stacked per quarter to show component contribution to a total.

#let d = (
  (q: "Q1", grp: "a", y: 3),
  (q: "Q1", grp: "b", y: 5),
  (q: "Q2", grp: "a", y: 4),
  (q: "Q2", grp: "b", y: 2),
  (q: "Q3", grp: "a", y: 6),
  (q: "Q3", grp: "b", y: 4),
)
#plot(
  data: d,
  mapping: aes(x: "q", y: "y", fill: "grp"),
  layers: (geom-col(position: "stack"),),
  width: 10cm,
  height: 6cm,
)

Stacked bar chart with three quarters on the x-axis and cumulative y on the y-axis; each bar splits into two coloured segments showing each group's contribution to the quarter total.

Stacked bar chart with three quarters on the x-axis and cumulative y on the y-axis; each bar splits into two coloured segments showing each group's contribution to the quarter total.

Stacked area chart over time, useful when the running total itself is informative.

#let d = ()
#for grp in ("a", "b", "c") {
  for i in range(0, 10) {
    d.push((x: i, y: i * 0.3 + (if grp == "b" { 1 } else if grp == "c" { 2 } else { 0 }), grp: grp))
  }
}
#plot(
  data: d,
  mapping: aes(x: "x", y: "y", fill: "grp"),
  layers: (geom-area(position: "stack", alpha: 0.6),),
  width: 10cm,
  height: 6cm,
)

Stacked area chart with x on the x-axis and cumulative y on the y-axis; three semi-transparent coloured bands rise from zero, each layer adding its contribution to a growing running total.

Stacked area chart with x on the x-axis and cumulative y on the y-axis; three semi-transparent coloured bands rise from zero, each layer adding its contribution to a growing running total.

Silhouette offset: each stack centred on zero (ThemeRiver).

#let d = ()
#for (gi, grp) in ("a", "b", "c").enumerate() {
  for i in range(0, 12) {
    let wave = calc.sin(i * 0.55 + gi * 1.1) * (0.35 + gi * 0.2)
    d.push((x: i, y: 1 + gi * 0.2 + wave, grp: grp))
  }
}
#plot(
  data: d,
  mapping: aes(x: "x", y: "y", fill: "grp"),
  layers: (
    geom-area(position: position-stack(offset: "silhouette")),
  ),
  width: 12cm,
  height: 6cm,
)

Streamgraph of three coloured bands flowing symmetrically around the zero line, with band thickness carrying each group's value over x = 0 to 11.

Streamgraph of three coloured bands flowing symmetrically around the zero line, with band thickness carrying each group's value over x = 0 to 11.

Wiggle offset: the baseline minimising boundary wiggle.

#let d = ()
#for (gi, grp) in ("a", "b", "c").enumerate() {
  for i in range(0, 12) {
    let wave = calc.sin(i * 0.55 + gi * 1.1) * (0.35 + gi * 0.2)
    d.push((x: i, y: 1 + gi * 0.2 + wave, grp: grp))
  }
}
#plot(
  data: d,
  mapping: aes(x: "x", y: "y", fill: "grp"),
  layers: (
    geom-area(position: position-stack(offset: "wiggle")),
  ),
  width: 12cm,
  height: 6cm,
)

Streamgraph of three coloured bands on a wiggle-minimising baseline, flowing organically around the zero line over x = 0 to 11.

Streamgraph of three coloured bands on a wiggle-minimising baseline, flowing organically around the zero line over x = 0 to 11.

See also

position-dodge, position-fill, position-identity.

Back to top