Тепловая карта (heatmap)

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


В Vega-Lite тепловая карта строится на основе трёх ключевых каналов:

  • x — категориальная или дискретная ось
  • y — категориальная или дискретная ось
  • color — количественное значение, отображаемое через цвет

Типичная структура данных представляет собой «длинный формат» (long format), где каждая строка — это отдельная ячейка матрицы:

[
  { "x": "A", "y": "1", "value": 10 },
  { "x": "A", "y": "2", "value": 20 },
  { "x": "B", "y": "1", "value": 5 },
  { "x": "B", "y": "2", "value": 15 }
]

Простейшая heatmap спецификация

В Vega-Lite heatmap задаётся через mark rect:

{
  "data": {
    "values": [
      { "x": "A", "y": "1", "value": 10 },
      { "x": "A", "y": "2", "value": 20 },
      { "x": "B", "y": "1", "value": 5 },
      { "x": "B", "y": "2", "value": 15 }
    ]
  },
  "mark": "rect",
  "encoding": {
    "x": { "field": "x", "type": "nominal" },
    "y": { "field": "y", "type": "nominal" },
    "color": { "field": "value", "type": "quantitative" }
  }
}

Ключевой момент: rect создаёт прямоугольники для каждой комбинации x/y, а цветовая шкала интерпретирует числовое значение.


Цветовые шкалы и их влияние на интерпретацию

Цвет в heatmap — основной носитель информации. В Vega-Lite он настраивается через scale.

Линейная шкала

"color": {
  "field": "value",
  "type": "quantitative",
  "scale": { "scheme": "blues" }
}

Линейные шкалы подходят для равномерных распределений.

Дивергентная шкала

"color": {
  "field": "value",
  "type": "quantitative",
  "scale": { "scheme": "redblue" }
}

Используется для данных с нулевой точкой отсчёта (например, отклонения).

Логарифмическое масштабирование

"color": {
  "field": "value",
  "type": "quantitative",
  "scale": { "type": "log" }
}

Полезно при сильной асимметрии данных.


Размер ячеек и управление геометрией

По умолчанию Vega-Lite автоматически распределяет прямоугольники по сетке. Однако можно явно управлять размером через width, height и padding:

"mark": {
  "type": "rect",
  "stroke": "white"
}

Добавление stroke улучшает читаемость плотных матриц, визуально разделяя ячейки.


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

Heatmap часто строится не из готовой матрицы, а из сырых данных. Vega-Lite поддерживает агрегацию прямо в encoding:

"color": {
  "aggregate": "mean",
  "field": "value",
  "type": "quantitative"
}

Другие полезные агрегаты:

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

Преобразование данных через трансформации

Vega предоставляет более низкоуровневые трансформации, которые в Vega-Lite упрощены через transform.

Фильтрация

"transform": [
  { "filter": "datum.value > 0" }
]

Визуализация логики категорий

"transform": [
  { "calculate": "datum.x + '-' + datum.y", "as": "key" }
]

Работа с пропущенными значениями

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

Стратегии:

  1. Явное заполнение нулями на уровне данных
  2. Использование null и настройка цвета:
"color": {
  "condition": {
    "test": "datum.value == null",
    "value": "#eeeeee"
  },
  "field": "value",
  "type": "quantitative"
}

Настройка легенды

Легенда heatmap определяет интерпретацию цветовой шкалы:

"legend": {
  "title": "Интенсивность",
  "orient": "right",
  "direction": "vertical"
}

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


Категориальные оси и сортировка

По умолчанию Vega-Lite сортирует категории лексикографически. Это можно переопределить:

"x": {
  "field": "x",
  "type": "nominal",
  "sort": ["B", "A", "C"]
}

Сортировка критична для временных рядов и UX-логики восприятия.


Heatmap на временных данных

Хотя heatmap чаще используется для категориальных матриц, временные данные также являются распространённым кейсом:

{
  "x": { "field": "date", "type": "temporal", "timeUnit": "month" },
  "y": { "field": "category", "type": "nominal" },
  "color": { "field": "value", "type": "quantitative" }
}

Использование timeUnit позволяет агрегировать данные по месяцам, неделям или дням.


Сглаживание восприятия через биннинг

Для непрерывных данных применяется биннинг:

"transform": [
  {
    "bin": true,
    "field": "value",
    "as": "binned_value"
  }
]

Это полезно при построении псевдо-heatmap из scatter-данных.


Множественные heatmap в одном представлении

Vega-Lite поддерживает фасетирование:

"facet": {
  "field": "group",
  "type": "nominal"
},
"spec": {
  "mark": "rect",
  "encoding": {
    "x": { "field": "x", "type": "nominal" },
    "y": { "field": "y", "type": "nominal" },
    "color": { "field": "value", "type": "quantitative" }
  }
}

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


Производительность и оптимизация

При больших объёмах данных heatmap может становиться узким местом рендеринга.

Практики оптимизации:

  • Предагрегация данных на сервере
  • Использование sample трансформации
  • Сокращение разрешения сетки (coarsening)
  • Избегание избыточных tooltip вычислений

Tooltip и интерактивность

Интерактивность в Vega-Lite ограничена по сравнению с Vega, но базовые возможности доступны:

"tooltip": [
  { "field": "x", "type": "nominal" },
  { "field": "y", "type": "nominal" },
  { "field": "value", "type": "quantitative" }
]

Дополнительно можно использовать selection:

"selection": {
  "highlight": {
    "type": "single",
    "on": "mouseover"
  }
}

Частые ошибки при построении heatmap

  • Использование числовых осей без биннинга, приводящее к «размазанной» сетке
  • Отсутствие сортировки категорий
  • Игнорирование пропусков данных
  • Слишком резкие цветовые шкалы без нормализации
  • Перегрузка визуализации избыточными метками

Расширенные сценарии применения

Heatmap в Vega и Vega-Lite применяется в различных аналитических задачах:

  • Анализ корреляций
  • Визуализация матриц переходов (Markov chains)
  • UI/UX анализ поведения пользователей
  • Финансовые матрицы доходности
  • Биологические экспрессии генов
  • Мониторинг системных логов

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