HAHS.
Back to Catalog

Stream Graph

chart

Also known as: streamgraph, stacked area chart, ThemeRiver

Show change over timeShow composition TemporalNumericalCategorical Line/Area

Description

A stream graph is a variation of the stacked area chart in which the layers are displaced around a central baseline rather than stacked from zero. This produces a flowing, organic shape that resembles a river or geological strata, where the width of each layer at any point in time represents the magnitude of that category. The total vertical extent of the stream at any moment encodes the sum of all categories.

The technique was popularized by Lee Byron and Martin Wattenberg in their 2008 paper “Stacked Graphs — Geometry & Aesthetics,” which also introduced the “streamgraph” name. They demonstrated that shifting the baseline to minimize layer wiggle (using the “weighted wiggle” algorithm) produces more aesthetically pleasing and perceptually stable layouts than traditional zero-baseline stacking. The result is a visualization that emphasizes the ebb and flow of categories over time, making temporal patterns in composition immediately visible.

Stream graphs trade precision for expressiveness. Because layers are not anchored to a common baseline, comparing the exact values of individual layers is harder than in a stacked bar chart or standard stacked area chart. However, the organic shape excels at conveying the gestalt: which categories are growing, shrinking, or dominating at different time periods. They are particularly effective for editorial and narrative visualizations where the goal is to convey the rhythm and dynamics of temporal data.

Stream Graph — interactive example

When to Use

  • Showing how the composition of a total changes over time (genre popularity, topic trends, species abundance)
  • Creating visually engaging editorial or narrative visualizations
  • When the overall shape and rhythm of change matters more than exact values
  • Displaying temporal data with 5-20 categories where you want to show both individual trends and total volume
  • When a standard stacked area chart looks too rigid and the audience values aesthetics

When NOT to Use

  • When precise value reading is essential — the floating baseline makes it hard to read individual layer values; use a stacked bar chart or line graph
  • When there are too many categories (>20) — thin layers become unreadable
  • When categories are not meaningfully stacked (they don’t sum to a meaningful total) — use separate line graphs
  • For data that is not temporal or sequential — the flowing shape implies continuity over time
  • When the audience is unfamiliar with the form and may misinterpret the shape

Anatomy

  • Layers (streams): Filled areas, one per category, stacked vertically around a central baseline. Width at any x-position encodes the category’s value.
  • Baseline: The central axis from which layers expand symmetrically (or asymmetrically, depending on the algorithm). Not a zero line.
  • Time axis: The horizontal axis showing the temporal dimension.
  • Color encoding: Each layer is a distinct color representing a category. A legend or direct labels identify them.
  • Outline strokes: Optional thin strokes separating layers to improve readability.
  • Tooltips: On-hover detail showing the category name, time point, and value, essential given the imprecision of the visual encoding.

Variations

  • Symmetric stream graph (silhouette): Layers expand equally above and below the center, producing the classic symmetric shape.
  • Weighted wiggle stream graph: The baseline is computed to minimize visual instability; the default in Byron and Wattenberg’s implementation.
  • Zero-baseline stacked area: Layers stack from zero upward; more precise but less visually dynamic.
  • Expanded (normalized) stream: Layer heights are scaled to fill 100% of the vertical space, showing only proportional change.
  • Interactive stream graph: Hovering highlights one layer across all time points; clicking isolates a single layer for detailed reading.

Code Reference

// Observable Plot - stream graph
Plot.plot({
  marks: [
    Plot.areaY(data, {
      x: "date",
      y: "value",
      fill: "category",
      curve: "basis",
      offset: "wiggle",
      tip: true
    })
  ],
  x: { label: "Date" },
  y: { label: null },
  color: { legend: true, label: "Category" }
})