Поле stack в кодировании

Роль стекового кодирования в визуализации

Стековое кодирование в Vega и Vega-Lite применяется для преобразования наборов значений в накопительные (stacked) представления, где отдельные компоненты суммируются вдоль выбранной оси. Основная цель — показать вклад категорий в общий итог, сохраняя при этом информацию о структуре составляющих.

В терминах спецификации визуализации стекирование относится к этапу преобразования данных, при котором исходные числовые значения заменяются интервалами [y0, y1] или [x0, x1]. Эти интервалы затем используются для построения областей, столбцов или полос, расположенных друг над другом.


Базовая семантика stack в Vega-Lite

В Vega-Lite стекирование чаще всего управляется через свойство stack внутри канала кодирования (encoding). Оно применяется к количественным каналам, обычно x или y, в сочетании с категориальным разбиением через color, detail или column.

Основные режимы:

  • "zero" — стек начинается от нуля
  • "center" — центрированное стековое отображение (streamgraph)
  • "normalize" — нормализация в проценты (100% stacked)
  • null / false — стекирование отключено

Стекирование по оси Y (наиболее частый случай)

Типичный сценарий — столбчатая диаграмма с накоплением:

{
  "mark": "bar",
  "encoding": {
    "x": {"field": "month", "type": "ordinal"},
    "y": {
      "field": "value",
      "type": "quantitative",
      "stack": "zero"
    },
    "color": {"field": "category", "type": "nominal"}
  }
}

В этом случае Vega-Lite автоматически:

  1. Группирует данные по x и color
  2. Сортирует категории стеков
  3. Вычисляет накопленные значения
  4. Создаёт скрытые поля y0 и y1

Результатом становится набор прямоугольников, расположенных друг над другом.


Внутренняя трансформация: y → y0, y1

При включении стекового режима Vega-Lite фактически переписывает данные. Каждое значение преобразуется в диапазон:

  • y0 — нижняя граница сегмента
  • y1 — верхняя граница сегмента

Пример логики:

category A: y0 = 0,  y1 = 10
category B: y0 = 10, y1 = 25
category C: y0 = 25, y1 = 40

Эта трансформация критична для mark-типов:

  • bar
  • area
  • rect

Стекирование по оси X

Хотя чаще используется вертикальное накопление, стекирование возможно и по горизонтали:

{
  "mark": "bar",
  "encoding": {
    "x": {
      "field": "value",
      "type": "quantitative",
      "stack": "zero"
    },
    "y": {"field": "group", "type": "nominal"},
    "color": {"field": "segment"}
  }
}

Здесь сумма строится вдоль оси X, что меняет визуальную интерпретацию: вместо вертикального накопления создаются горизонтальные сегменты.


Режим normalize: процентное распределение

Режим "normalize" преобразует абсолютные значения в доли от общего итога внутри группы.

Формально:

y' = y / sum(y_group)

Пример:

{
  "mark": "bar",
  "encoding": {
    "x": {"field": "year", "type": "ordinal"},
    "y": {
      "field": "sales",
      "type": "quantitative",
      "stack": "normalize"
    },
    "color": {"field": "product"}
  }
}

Такой режим используется для сравнения структуры распределений между группами при различающихся абсолютных масштабах.


Режим center: streamgraph-подобная модель

"center" смещает стек относительно центральной линии, создавая симметричную композицию:

       ▲
   ____│____
  /    │    \
 /     │     \

Внутренне значения центрируются относительно нуля:

y0 = cumulative - total/2
y1 = y0 + value

Этот режим часто применяется для потоковых диаграмм (streamgraph), где важна динамика вкладов во времени.


Отключение стекирования

Если стекирование не требуется, используется:

"stack": null

или:

"stack": false

В этом случае значения интерпретируются как независимые, и элементы могут перекрывать друг друга или отображаться рядом в зависимости от mark-типа и других настроек.


Автоматическое стекирование в Vega-Lite

Vega-Lite способен включать стекирование неявно, даже если stack не задан явно. Это происходит при выполнении условий:

  • количественная ось (quantitative)
  • категориальная группировка
  • наличие color, detail или facet
  • mark поддерживает stacking (bar, area)

В таких случаях поведение по умолчанию эквивалентно "stack": "zero".


Взаимодействие stack с transform-операциями

Стекирование может конфликтовать или комбинироваться с трансформациями данных:

Aggregate

При использовании агрегации (sum, count, mean) стекирование выполняется после агрегации:

{
  "aggregate": [{"op": "sum", "field": "value", "as": "total"}]
}

После этого применяется stack к total.


Bin

Для биннинга стекирование применяется к уже дискретизированным интервалам:

  • значения сначала группируются в интервалы
  • затем суммируются внутри бинов
  • после этого строится стек

Calculate

Вычисляемые поля не влияют на механику стекирования, но могут менять основу суммирования.


Явный transform: stack transform

Помимо encoding-level stack, Vega предоставляет более низкоуровневый transform:

{
  "transform": [
    {
      "stack": "value",
      "groupby": ["category"],
      "sort": {"field": "value"},
      "as": ["y0", "y1"]
    }
  ]
}

Ключевые параметры:

  • stack — поле для суммирования
  • groupby — разбиение стеков
  • sort — порядок укладки сегментов
  • as — имена выходных полей

Этот вариант используется, когда требуется полный контроль над процессом стекирования.


Сортировка стеков

Порядок наложения категорий критически влияет на результат визуализации. Vega-Lite использует:

  • порядок данных
  • или сортировку по color
  • или явный sort в encoding

Пример:

"color": {
  "field": "type",
  "sort": "ascending"
}

Неправильная сортировка может привести к визуально искажённым результатам, особенно в area charts.


Ограничения и особенности поведения

Стекирование не применяется в следующих случаях:

  • mark: line
  • отсутствие количественного канала
  • несовместимые шкалы (scale)

Также важно учитывать:

  • отрицательные значения стекуются отдельно (в сторону отрицательной оси)
  • смешанные знаки создают две независимые стопки
  • при normalize отрицательные значения игнорируются или требуют предварительной обработки

Обработка отрицательных значений

При наличии отрицательных данных стек разделяется:

positive stack → вверх
negative stack → вниз

Это реализуется через раздельное накопление сумм:

  • positive cumulative sum
  • negative cumulative sum

Такой подход предотвращает смешение направлений и сохраняет корректную геометрию диаграммы.


Практическая модель вычисления

Алгоритм стекирования можно представить следующим образом:

  1. Группировка по ключу (например, x + color)
  2. Разделение значений на положительные и отрицательные
  3. Сортировка внутри группы
  4. Последовательное накопление суммы
  5. Запись интервалов [y0, y1]
  6. Передача в rendering pipeline

Связь stack с area и bar mark

Наиболее тесная интеграция наблюдается с:

  • bar — вертикальные/горизонтальные накопленные столбцы
  • area — заполненные области между кривыми

Для area стекирование определяет форму многоуровневой поверхности, где каждая серия данных формирует слой.


Итоговая модель представления

Поле stack в Vega-Lite — это декларативный механизм управления накопительными преобразованиями, который скрывает сложность расчёта границ интервалов и предоставляет унифицированный способ построения сложных многослойных визуализаций.