Трансформации источников данных

Роль трансформаций в конвейере визуализации

В Vega и Vega-Lite данные проходят через формализованный этап преобразования перед тем, как попасть в слой масштабирования и отрисовки. Трансформации определяют, каким образом исходный набор данных приводится к виду, пригодному для визуального представления: фильтрация, агрегация, преобразование типов, создание вычисляемых полей и структурирование многомерных данных.

В Vega-Lite трансформации описываются декларативно в секции transform, тогда как в Vega они являются частью графа потоковой обработки данных и представлены как отдельные узлы dataflow.

Ключевая идея заключается в том, что визуализация строится не на «сырых» данных, а на последовательности детерминированных преобразований, где каждый шаг формирует новый слой данных.


Базовая структура трансформаций в Vega-Lite

В Vega-Lite трансформации задаются внутри объекта спецификации:

{
  "data": {
    "url": "data.csv"
  },
  "transform": [
    { "filter": "datum.value > 10" },
    { "calculate": "datum.value * 2", "as": "scaled" }
  ],
  "mark": "bar",
  "encoding": {
    "x": { "field": "category", "type": "nominal" },
    "y": { "field": "scaled", "type": "quantitative" }
  }
}

Каждый элемент массива transform выполняется последовательно, формируя цепочку преобразований. Порядок имеет критическое значение: результат одного шага становится входом для следующего.


Фильтрация данных

Фильтрация — одна из самых часто используемых трансформаций. Она позволяет ограничить набор данных по условию.

Логические выражения

{ "filter": "datum.sales > 100" }

Фильтрация использует выражения Vega Expression Language. Внутри доступны:

  • datum — текущая строка данных
  • математические операции
  • логические операторы
  • встроенные функции

Сложные условия

{
  "filter": "datum.sales > 100 && datum.region === 'Europe'"
}

Фильтрация может опираться на вычисляемые поля, если они были созданы ранее в цепочке трансформаций.


Вычисляемые поля (calculate)

Трансформация calculate добавляет новое поле в набор данных на основе выражения.

{
  "calculate": "datum.revenue - datum.cost",
  "as": "profit"
}

Особенности вычислений

  • создаёт новый столбец без изменения исходных данных
  • поддерживает числовые, строковые и логические операции
  • допускает использование встроенных функций (например, log, floor, datetime)

Пример нормализации данных

{
  "calculate": "datum.value / 1000",
  "as": "value_k"
}

Агрегация данных

Трансформация aggregate используется для группировки и вычисления статистик.

{
  "aggregate": [
    { "op": "mean", "field": "score", "as": "avg_score" }
  ],
  "groupby": ["category"]
}

Основные операции агрегации

  • count — количество записей
  • sum — сумма значений
  • mean — среднее
  • median — медиана
  • min / max — экстремумы

Группировка

Поле groupby определяет разбиение данных. Без него агрегирование применяется ко всему набору.


Биннинг (bin)

Биннинг используется для преобразования непрерывных данных в интервалы.

{
  "bin": true,
  "field": "age",
  "as": "age_bin"
}

Управление параметрами бинов

{
  "bin": {
    "maxbins": 10
  },
  "field": "value",
  "as": "value_bin"
}

Применение

  • построение гистограмм
  • дискретизация числовых данных
  • подготовка данных для тепловых карт

Работа со временем (timeUnit)

Трансформация timeUnit преобразует временные значения в агрегированные временные единицы.

{
  "timeUnit": "yearmonth",
  "field": "date",
  "as": "year_month"
}

Типичные временные уровни

  • year
  • month
  • day
  • hours
  • комбинированные: yearmonth, yearmonthdate

Использование

Позволяет группировать временные ряды без предварительной подготовки данных.


Преобразование структуры (fold и flatten)

Fold: «широкие» данные → «длинные»

{
  "fold": ["sales_q1", "sales_q2", "sales_q3"],
  "as": ["quarter", "value"]
}

Результат:

quarter value
sales_q1 100
sales_q2 150

Используется для построения сравнительных диаграмм и stacked визуализаций.


Flatten: работа с массивами

{
  "flatten": ["items"]
}

Если поле содержит массив, flatten разворачивает его в отдельные строки.


Переименование и переструктурирование (project / formula-like patterns)

Хотя в Vega-Lite нет отдельной трансформации rename, подобное поведение достигается через calculate и as, либо на уровне подготовки данных.


Оконные функции (window)

Трансформация window позволяет выполнять вычисления по скользящим окнам.

{
  "window": [
    {
      "op": "sum",
      "field": "value",
      "as": "running_total"
    }
  ],
  "sort": [{ "field": "date" }]
}

Возможности

  • скользящие суммы
  • ранжирование (rank)
  • накопительные значения
  • разницы между соседними элементами

Пример ранжирования

{
  "window": [
    { "op": "rank", "as": "rank" }
  ],
  "sort": [{ "field": "score", "order": "descending" }]
}

Lookup: объединение наборов данных

Трансформация lookup используется для соединения двух источников данных по ключу.

{
  "lookup": "id",
  "from": {
    "data": { "url": "categories.json" },
    "key": "id",
    "fields": ["name"]
  }
}

Модель работы

  • основной датасет содержит ключ
  • внешний датасет содержит справочные данные
  • результат — обогащённая структура

Используется вместо классического JOIN в SQL.


Агрегация после биннинга

Частый паттерн:

{
  "bin": { "maxbins": 20 },
  "field": "value",
  "as": "bin_value"
},
{
  "aggregate": [
    { "op": "count", "as": "count" }
  ],
  "groupby": ["bin_value"]
}

Это основа построения гистограмм в Vega-Lite.


Вложенные трансформации и порядок выполнения

Порядок трансформаций строго фиксирован. Например:

"transform": [
  { "filter": "datum.value > 0" },
  { "calculate": "datum.value * 2", "as": "v2" },
  { "aggregate": [{ "op": "mean", "field": "v2", "as": "avg" }] }
]

Важное поведение

  • фильтр уменьшает объём данных до вычислений
  • calculate создаёт новые поля
  • aggregate полностью перестраивает структуру данных

Различия трансформаций Vega и Vega-Lite

Vega-Lite

  • декларативный стиль
  • ограниченный набор трансформаций
  • автоматическая генерация Vega-графа

Vega

  • низкоуровневый dataflow
  • каждая трансформация — узел графа
  • больше гибкости

Пример Vega transform:

{
  "type": "filter",
  "expr": "datum.value > 10"
}

или

{
  "type": "formula",
  "as": "profit",
  "expr": "datum.revenue - datum.cost"
}

Композиция трансформаций как вычислительный граф

В Vega трансформации формируют направленный граф обработки данных:

  • узлы: трансформации
  • рёбра: потоки данных
  • состояние: промежуточные таблицы

Такой подход позволяет:

  • эффективно пересчитывать изменения
  • переиспользовать промежуточные результаты
  • масштабировать обработку данных

Типичные ошибки при использовании трансформаций

Нарушение порядка

Агрегация до фильтрации может привести к некорректным результатам.

Конфликт типов

Например, применение timeUnit к строковому полю без даты.

Потеря данных после aggregate

После агрегации теряются исходные строки, что влияет на последующие трансформации.


Комбинирование трансформаций в аналитических сценариях

Типовой пайплайн:

  1. фильтрация шумовых данных
  2. вычисление новых метрик
  3. преобразование времени
  4. агрегация
  5. построение визуального слоя
"transform": [
  { "filter": "datum.value != null" },
  { "calculate": "datum.value * 1.2", "as": "adj_value" },
  { "timeUnit": "yearmonth", "field": "date", "as": "ym" },
  {
    "aggregate": [
      { "op": "sum", "field": "adj_value", "as": "total" }
    ],
    "groupby": ["ym"]
  }
]