В Vega и Vega-Lite данные проходят через формализованный этап преобразования перед тем, как попасть в слой масштабирования и отрисовки. Трансформации определяют, каким образом исходный набор данных приводится к виду, пригодному для визуального представления: фильтрация, агрегация, преобразование типов, создание вычисляемых полей и структурирование многомерных данных.
В Vega-Lite трансформации описываются декларативно в секции
transform, тогда как в Vega они являются частью графа
потоковой обработки данных и представлены как отдельные узлы
dataflow.
Ключевая идея заключается в том, что визуализация строится не на «сырых» данных, а на последовательности детерминированных преобразований, где каждый шаг формирует новый слой данных.
В 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": "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": true,
"field": "age",
"as": "age_bin"
}
{
"bin": {
"maxbins": 10
},
"field": "value",
"as": "value_bin"
}
Трансформация timeUnit преобразует временные значения в
агрегированные временные единицы.
{
"timeUnit": "yearmonth",
"field": "date",
"as": "year_month"
}
yearmonthdayhoursyearmonth,
yearmonthdateПозволяет группировать временные ряды без предварительной подготовки данных.
{
"fold": ["sales_q1", "sales_q2", "sales_q3"],
"as": ["quarter", "value"]
}
Результат:
| quarter | value |
|---|---|
| sales_q1 | 100 |
| sales_q2 | 150 |
Используется для построения сравнительных диаграмм и stacked визуализаций.
{
"flatten": ["items"]
}
Если поле содержит массив, flatten разворачивает его в
отдельные строки.
Хотя в Vega-Lite нет отдельной трансформации rename,
подобное поведение достигается через calculate и
as, либо на уровне подготовки данных.
Трансформация 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": "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" }] }
]
Пример Vega transform:
{
"type": "filter",
"expr": "datum.value > 10"
}
или
{
"type": "formula",
"as": "profit",
"expr": "datum.revenue - datum.cost"
}
В Vega трансформации формируют направленный граф обработки данных:
Такой подход позволяет:
Агрегация до фильтрации может привести к некорректным результатам.
Например, применение timeUnit к строковому полю без
даты.
После агрегации теряются исходные строки, что влияет на последующие трансформации.
Типовой пайплайн:
"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"]
}
]