HAHS.
Back to Catalog

Stream Graph

chart

Also known as: streamgraph, stacked area chart, ThemeRiver

Show change over timeShow composition TemporalNumericalCategorical Line/Area

설명 / Description

스트림 그래프는 누적 영역 차트의 변형으로, 레이어가 0에서부터 쌓이는 대신 중심 기준선 주변에 배치됩니다. 이는 강이나 지질층을 연상시키는 유기적이고 흐르는 듯한 형태를 만들어내며, 특정 시점에서 각 레이어의 너비는 해당 범주의 크기를 나타냅니다. 어느 순간이든 스트림의 전체 수직 폭은 모든 범주의 합을 인코딩합니다.

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.

이 기법은 리 바이런(Lee Byron)과 마틴 와텐버그(Martin Wattenberg)가 2008년 논문 "Stacked Graphs -- Geometry & Aesthetics"에서 대중화했으며, 이 논문에서 "스트림그래프"라는 이름도 처음 소개되었습니다. 이들은 레이어의 흔들림을 최소화하도록 기준선을 이동시키는 방식("가중 흔들림" 알고리즘)이 전통적인 제로 기준선 스태킹보다 더 미적으로 만족스럽고 지각적으로 안정적인 레이아웃을 만들어낸다는 것을 보였습니다. 그 결과는 시간에 따른 범주의 성쇠를 강조하여 구성의 시간적 패턴을 즉시 눈에 띄게 만드는 시각화입니다.

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
  • 개별 추세와 총량을 모두 보여주고 싶은 5~20개 범주의 시간적 데이터를 표시할 때
  • 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
  • 범주가 너무 많은 경우(20개 초과) -- 얇은 레이어는 읽기 어려워집니다
  • 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

  • 레이어(스트림): 범주당 하나씩, 중심 기준선 주위에 수직으로 쌓인 채워진 영역입니다. 임의의 x 위치에서의 너비는 해당 범주의 값을 인코딩합니다.
  • 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.
  • 제로 기준선 누적 영역: 레이어가 0에서부터 위로 쌓입니다; 더 정밀하지만 시각적 역동성은 덜합니다.
  • Zero-baseline stacked area: Layers stack from zero upward; more precise but less visually dynamic.
  • 확장(정규화) 스트림: 레이어 높이가 수직 공간의 100%를 채우도록 스케일링되어, 비례적 변화만 보여줍니다.
  • 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" }
})