Трансформация tree и treemap

Иерархические визуализации в Vega и Vega-Lite опираются на преобразование плоских наборов данных в древовидные структуры. Ключевая особенность таких трансформаций заключается в переходе от таблицы записей к иерархии узлов с вычисленными координатами, глубиной, размерами и вложенностью. В основе лежат три основных этапа: формирование иерархии, вычисление структуры дерева и последующая упаковка пространства (layout), включая алгоритмы tree, treemap, pack и partition.


Иерархические данные в Vega описываются как дерево, где каждый узел содержит:

  • идентификатор (id)
  • ссылку на родителя (parent)
  • числовые показатели (value)
  • вложенные дочерние элементы (children)

Однако исходные данные почти всегда представлены в плоском виде:

[
  { "id": "A", "parent": null, "value": 10 },
  { "id": "B", "parent": "A", "value": 5 },
  { "id": "C", "parent": "A", "value": 3 }
]

Для преобразования используется этап stratify.


Transform stratify: построение дерева

Transform stratify выполняет преобразование плоского списка в иерархическую структуру.

Основные параметры:

  • key — уникальный идентификатор узла
  • parentKey — ссылка на родителя
  • root — корневой узел (если требуется явное задание)

Принцип работы:

  1. создаётся индекс всех узлов по key
  2. каждому элементу назначается родитель
  3. формируется дерево вложенности
  4. вычисляется корневой узел

Пример конфигурации:

{
  "transform": [
    {
      "type": "stratify",
      "key": "id",
      "parentKey": "parent"
    }
  ]
}

Результат этого этапа ещё не содержит координат — только структуру.


Tree transform: вычисление компоновки дерева

После построения иерархии применяется tree transform, который вычисляет координаты узлов для древовидной визуализации.

Алгоритм tree

Алгоритм строит классическое дерево:

  • корень располагается в начальной точке
  • дети размещаются на следующем уровне
  • используется стратегия обхода (DFS/BFS)
  • координаты рассчитываются по осям x/y

Основные параметры:

  • size — размер области (ширина и высота)
  • nodeSize — фиксированный размер узла
  • separation — расстояние между узлами
  • as — имена выходных полей (x, y, depth и т.д.)

Пример:

{
  "transform": [
    {
      "type": "stratify",
      "key": "id",
      "parentKey": "parent"
    },
    {
      "type": "tree",
      "method": "tidy",
      "size": [800, 400],
      "separation": true,
      "as": ["x", "y", "depth", "children"]
    }
  ]
}

Особенности tree-layout:

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

Treemap transform: плотная упаковка иерархий

Transform treemap применяется для отображения иерархических данных в виде вложенных прямоугольников, где площадь каждого прямоугольника пропорциональна значению узла.

Принцип работы:

  1. вычисляется сумма значений в поддереве
  2. пространство рекурсивно делится
  3. каждый узел получает прямоугольную область
  4. вложенные узлы размещаются внутри родительского прямоугольника

Алгоритм treemap

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

Ключевая идея:

  • стремление к квадратным формам
  • уменьшение вытянутых прямоугольников
  • балансировка по площади

Основные параметры treemap

  • field — поле значений (например, value)
  • size — размеры области визуализации
  • round — округление координат
  • padding — внутренние отступы
  • ratio — контроль соотношения сторон
  • sort — сортировка узлов перед разбиением

Пример конфигурации treemap

{
  "transform": [
    {
      "type": "stratify",
      "key": "id",
      "parentKey": "parent"
    },
    {
      "type": "treemap",
      "field": "value",
      "size": [800, 600],
      "paddingInner": 2,
      "paddingOuter": 4,
      "ratio": 1.6,
      "as": ["x0", "y0", "x1", "y1", "depth", "children"]
    }
  ]
}

Геометрия результата treemap

Каждый узел получает координаты:

  • x0, y0 — левый верхний угол
  • x1, y1 — правый нижний угол

Из них вычисляются:

  • ширина = x1 - x0
  • высота = y1 - y0
  • площадь = (x1 - x0) * (y1 - y0)

Эти значения напрямую используются для построения прямоугольников.


Сравнение tree и treemap

Tree layout:

  • узлы располагаются по уровням
  • сохраняется структура ветвления
  • оптимально для анализа зависимостей
  • плохо использует пространство

Treemap layout:

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

Влияние агрегации данных

Перед применением treemap часто требуется агрегация значений:

  • суммирование дочерних узлов
  • вычисление веса поддерева
  • нормализация значений

Пример агрегации:

{
  "transform": [
    {
      "type": "stratify",
      "key": "id",
      "parentKey": "parent"
    },
    {
      "type": "treemap",
      "field": "value",
      "method": "sum"
    }
  ]
}

Управление отступами и визуальной иерархией

Padding влияет на читаемость структуры:

  • paddingInner — расстояние между дочерними элементами
  • paddingOuter — отступ от границ родителя
  • paddingTop / Bottom / Left / Right — асимметричные отступы

Эти параметры позволяют выделять уровни вложенности и предотвращать визуальное слипание элементов.


Цветовое кодирование уровней

Иерархические трансформации часто дополняются цветовой схемой:

  • depth (глубина узла)
  • value (размер)
  • categorical encoding (тип узла)

Типичный подход:

  • корневой уровень — нейтральный цвет
  • промежуточные уровни — градиент
  • листья — насыщенные оттенки

Производительность и масштабирование

При больших деревьях (тысячи и десятки тысяч узлов) treemap и tree требуют оптимизации:

  • предварительная агрегация данных
  • ограничение глубины отображения
  • lazy computation вложенных узлов
  • использование кэширования layout-результатов

Treemap особенно чувствителен к числу узлов из-за рекурсивного деления пространства.


Особенности интеграции в Vega-Lite

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

  • transform stratify
  • transform treemap
  • mark type (rect, text)
  • encoding (x, y, width, height)

Пример упрощённой спецификации:

{
  "data": {"name": "table"},
  "transform": [
    {
      "type": "stratify",
      "key": "id",
      "parentKey": "parent"
    },
    {
      "type": "treemap",
      "field": "value"
    }
  ],
  "mark": "rect",
  "encoding": {
    "x": {"field": "x0"},
    "x2": {"field": "x1"},
    "y": {"field": "y0"},
    "y2": {"field": "y1"}
  }
}

Комбинирование tree и treemap в одной модели

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

  • tree используется для навигации структуры
  • treemap — для анализа распределения значений
  • pack — для кластеризации без прямоугольной сетки
  • partition — для радиальных диаграмм

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