Разрешение шкал и осей: resolve

В композиционных спецификациях Vega-Lite (layer, concat, facet, repeat) несколько визуализаций могут сосуществовать в одном графике, при этом каждая из них потенциально определяет собственные шкалы (scales), оси (axes) и легенды (legends). Ключевая задача механизма resolve — определить, какие из этих компонентов будут разделяемыми (shared), а какие — независимыми (independent) для каждой дочерней визуализации.

Без явного управления разрешением Vega-Lite применяет набор эвристик, которые могут приводить к неожиданному поведению в сложных компоновках. Поэтому resolve является центральным инструментом контроля согласованности координатных систем.


Базовая структура resolve

В спецификации композиции объект resolve описывается на уровне контейнера:

{
  "resolve": {
    "scale": {},
    "axis": {},
    "legend": {}
  }
}

Каждое поле управляет соответствующим типом визуального компонента:

  • scale — разрешение шкал (x, y, color и т.д.)
  • axis — поведение осей (ticks, labels, grid)
  • legend — поведение легенд для закодированных полей

Разрешение шкал (scale resolution)

Шкалы определяют отображение данных в координатное пространство. В композиции Vega-Lite одна и та же шкала может:

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

Возможные стратегии

Для каждой шкалы можно задать:

  • "shared" — единая шкала для всех дочерних представлений
  • "independent" — отдельная шкала для каждого представления

Пример:

{
  "resolve": {
    "scale": {
      "y": "shared",
      "color": "independent"
    }
  }
}

Поведение shared шкал

При использовании "shared":

  • вычисляется единый domain (минимум/максимум) по всем дочерним данным
  • все подграфики используют одинаковое отображение значений
  • обеспечивается визуальная сопоставимость

Это критично для:

  • сравнительных графиков
  • small multiples с общей вертикальной шкалой
  • наложенных временных рядов

Поведение independent шкал

При "independent":

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

Типичный случай применения:

  • facet-панели с разными диапазонами данных
  • нормализованные сравнения форм распределений

Разрешение осей (axis resolution)

Оси в Vega-Lite связаны со шкалами, но имеют собственные параметры: подписи, сетку, деления, форматирование.

{
  "resolve": {
    "axis": {
      "x": "shared",
      "y": "independent"
    }
  }
}

Shared axis

При shared:

  • ось рисуется один раз на уровне композиции
  • все дочерние представления используют общие ticks и labels
  • предотвращается дублирование визуального шума

Особенно важно в:

  • layered charts
  • concatenated views с одинаковой шкалой

Independent axis

При independent:

  • каждая панель имеет собственную ось
  • возможно различие в форматах подписей
  • увеличивается гибкость, но снижается компактность

Разрешение легенд (legend resolution)

Легенды отображают соответствие между данными и визуальными кодировками (например, цветами или формами).

{
  "resolve": {
    "legend": {
      "color": "shared"
    }
  }
}

Shared легенды

При shared:

  • одна легенда объединяет все дочерние представления
  • значения домена объединяются
  • цвета и категории унифицируются

Это важно для:

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

Independent легенды

При independent:

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

Поведение resolve в различных типах компоновки

Layer (наложение слоёв)

В layer все слои обычно используют общие шкалы, поскольку они находятся в одной координатной системе:

{
  "layer": [
    { "mark": "line", "encoding": { "y": { "field": "a", "type": "quantitative" } } },
    { "mark": "point", "encoding": { "y": { "field": "b", "type": "quantitative" } } }
  ],
  "resolve": {
    "scale": {
      "y": "shared"
    }
  }
}

Здесь shared y-шкала обеспечивает корректное наложение линий и точек.


Concat (горизонтальная/вертикальная конкатенация)

При concat каждая панель может быть как независимой, так и синхронизированной:

{
  "concat": [
    { "mark": "bar", "encoding": { "x": { "field": "a" } } },
    { "mark": "bar", "encoding": { "x": { "field": "b" } } }
  ],
  "resolve": {
    "scale": {
      "x": "independent"
    }
  }
}

Это позволяет сравнивать формы распределений без привязки к абсолютным значениям.


Facet (разбиение по категориям)

Facet создаёт набор повторяющихся подграфиков. Здесь resolve особенно критичен:

{
  "facet": {
    "row": { "field": "category", "type": "nominal" }
  },
  "spec": {
    "mark": "line",
    "encoding": {
      "x": { "field": "year", "type": "temporal" },
      "y": { "field": "value", "type": "quantitative" }
    }
  },
  "resolve": {
    "scale": {
      "y": "shared"
    },
    "axis": {
      "x": "shared"
    }
  }
}

Shared y-шкала обеспечивает сопоставимость категорий, а shared x-ось синхронизирует временную шкалу.


Приоритеты разрешения и наследование

При вычислении итоговой визуализации Vega-Lite использует следующий порядок:

  1. Явно заданный resolve
  2. Параметры композиции (facet/concat/layer)
  3. Эвристики Vega-Lite
  4. Дефолтные значения (обычно independent для facet)

Важно, что resolve всегда переопределяет автоматические решения.


Конфликты шкал и их устранение

В композициях часто возникают конфликты:

Разные domains

Если две панели используют shared шкалу, но данные имеют сильно разные диапазоны, происходит:

  • сжатие одной из визуализаций
  • потеря детализации

Решение:

  • переход на independent
  • либо нормализация данных

Несовпадающие типы кодировок

Если один слой использует quantitative, а другой nominal шкалу цвета:

  • shared color-scale становится невозможной
  • Vega-Lite автоматически переключает поведение на independent

Несогласованные оси

При попытке объединить несовместимые оси:

  • оси могут дублироваться
  • форматирование может конфликтовать

Решается через:

"axis": {
  "x": "shared"
}

или отключением осей на уровне одного слоя:

"axis": null

Связь resolve со структурой Vega

На более низком уровне Vega (не Vega-Lite) используется концепция resolve в group marks:

  • scale
  • axis
  • legend

Vega-Lite транслирует декларативные настройки в Vega runtime, где:

  • shared шкалы становятся общими signal-based scales
  • independent шкалы компилируются в отдельные scale objects

Практика проектирования resolve-стратегий

При проектировании сложных визуализаций важно учитывать:

  • смысл сравнения (абсолютный vs относительный)
  • необходимость общей шкалы восприятия
  • плотность информации на экране
  • семантическую связность данных

Типовые паттерны:

  • shared y + independent x — сравнение форм распределений
  • shared x + shared y — строгая сопоставимость панелей
  • independent color + shared axes — разные категории на единой шкале

Влияние resolve на интерактивность

При использовании интерактивных трансформаций (filter, brush, zoom):

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

Это влияет на:

  • linked brushing
  • coordinated views
  • cross-filtering

Типовые ошибки при использовании resolve

  • чрезмерное использование shared шкал без учета диапазонов
  • смешивание incompatible encodings в одной легенде
  • ожидание синхронизации без явного задания axis resolve
  • игнорирование влияния facet default behavior

Эти ошибки приводят к:

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