Фасетинг в Vega-Lite представляет собой механизм разбиения одного набора данных на множество подграфиков (панелей), каждая из которых отображает отдельную подвыборку данных в едином визуальном шаблоне. Концепция основана на идее small multiples: повторяющихся графиков одинаковой структуры, но с разными срезами данных. Это позволяет одновременно сравнивать распределения, тренды и зависимости между группами, сохраняя единообразие визуального кодирования.
Фасетинг в Vega и Vega-Lite реализуется декларативно: описывается не
процесс построения графиков, а структура разбиения данных и правила
отображения. Основная логика сосредоточена вокруг свойства
facet, которое определяет поле группировки и способ
компоновки панелей.
Фасетинг опирается на группировку данных по категориальному признаку. Каждое уникальное значение выбранного поля становится отдельной панелью.
Минимальная структура:
{
"data": { "url": "data.csv" },
"facet": {
"row": { "field": "category", "type": "nominal" }
},
"spec": {
"mark": "bar",
"encoding": {
"x": { "field": "value", "type": "quantitative" },
"y": { "field": "name", "type": "nominal" }
}
}
}
Здесь:
facet.row задаёт разбиение по строкамcategory создаёт отдельную панельspec описывает внутренний график, повторяемый для
каждой группыФасетинг не изменяет исходный датасет, он лишь логически сегментирует его перед отрисовкой.
Фасетинг может быть одномерным или двумерным.
"facet": {
"row": {
"field": "region",
"type": "nominal"
}
}
Каждая строка сетки соответствует отдельной категории.
"facet": {
"column": {
"field": "year",
"type": "ordinal"
}
}
Каждый столбец соответствует значению временной или порядковой переменной.
"facet": {
"row": { "field": "region", "type": "nominal" },
"column": { "field": "product", "type": "nominal" }
}
Такой подход формирует матрицу подграфиков, где каждая ячейка — комбинация двух категорий. Это классический случай применения фасетинга в аналитических панелях.
Поле фасетинга может быть дополнено преобразованием:
Пример с бинами:
"facet": {
"column": {
"field": "age",
"bin": true,
"type": "quantitative"
}
}
В этом случае данные группируются по интервалам возраста, а каждая панель соответствует диапазону значений.
Ключевая особенность архитектуры Vega-Lite — вложенный
spec. Он определяет, что именно рисуется внутри каждой
панели.
{
"facet": {
"row": { "field": "country", "type": "nominal" }
},
"spec": {
"mark": "line",
"encoding": {
"x": { "field": "date", "type": "temporal" },
"y": { "field": "value", "type": "quantitative" }
}
}
}
Один и тот же график применяется ко всем группам данных, но каждая группа получает свой независимый контекст данных.
Один из центральных аспектов фасетинга — управление шкалами.
По умолчанию Vega-Lite может:
Это регулируется через resolve:
"resolve": {
"scale": {
"y": "independent"
}
}
"shared" — общий масштаб для всех панелей"independent" — отдельный масштаб для каждой
панелиИспользование независимых шкал полезно, когда группы имеют разные порядки величин, например, доходы разных стран.
Vega-Lite автоматически рассчитывает сетку, но поведение можно контролировать через параметры компоновки:
spacing — расстояние между панелямиcolumns — количество столбцов (для row-facet)align — выравнивание осейПример:
{
"facet": {
"row": { "field": "category", "type": "nominal" },
"columns": 3
},
"spec": {
"mark": "bar",
"encoding": {
"x": { "field": "value", "type": "quantitative" },
"y": { "field": "item", "type": "nominal" }
}
}
}
Здесь панели будут распределены по строкам, но максимум три столбца в каждой строке.
Фасетинг часто комбинируется с агрегированными полями. Внутри каждой панели можно вычислять статистику отдельно:
"encoding": {
"x": {
"aggregate": "mean",
"field": "value",
"type": "quantitative"
}
}
Это означает, что каждая панель показывает среднее значение для своей группы.
Важно, что агрегация выполняется после разделения данных по фасетам, а не до него.
В Vega-Lite существует два механизма многократного отображения:
facet — разделение данных по группамrepeat — повторение одного графика с разными
полямиРазличие фундаментальное:
| Механизм | Основание | Результат |
|---|---|---|
| facet | данные | группы панелей |
| repeat | поля | набор одинаковых графиков |
Пример repeat:
"repeat": {
"column": ["a", "b", "c"]
}
Пример facet:
"facet": {
"column": { "field": "type", "type": "nominal" }
}
Фасетинг может быть вложенным, создавая иерархические структуры:
{
"facet": {
"row": { "field": "continent", "type": "nominal" }
},
"spec": {
"facet": {
"column": { "field": "country", "type": "nominal" }
},
"spec": {
"mark": "line",
"encoding": {
"x": { "field": "year", "type": "temporal" },
"y": { "field": "gdp", "type": "quantitative" }
}
}
}
}
Такая структура формирует многоуровневую сетку: континенты → страны → временные ряды.
Фасетинг чувствителен к пропущенным данным. Vega-Lite предоставляет несколько стратегий:
Пример фильтрации:
"transform": [
{ "filter": "datum.category != null" }
]
Это позволяет избежать появления пустых панелей.
Порядок панелей не всегда совпадает с лексикографическим порядком значений. Его можно контролировать:
"facet": {
"row": {
"field": "category",
"type": "nominal",
"sort": ["A", "B", "C"]
}
}
Также возможна сортировка по агрегированным значениям:
"sort": { "op": "mean", "field": "value", "order": "descending" }
При большом количестве уникальных значений фасетинг становится ресурсоёмким:
Практическое ограничение часто связано не с Vega-Lite, а с браузерным отрисовщиком.
Оптимизации:
Все панели наследуют единый визуальный стиль, но допускают локальные переопределения:
"spec": {
"mark": {
"type": "line",
"strokeWidth": 2
}
}
При необходимости можно изменять оформление через условные выражения:
"color": {
"condition": {
"test": "datum.value > 100",
"value": "red"
},
"value": "blue"
}
Фасетинг в Vega-Lite выступает не просто механизмом компоновки, а способом структурирования анализа:
Каждая панель становится независимой аналитической единицей, но остаётся частью общей визуальной системы, управляемой единым спецификационным описанием.