Двойные оси: layer с независимыми шкалами

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

Ключевая особенность слоя заключается в том, что визуальные элементы объединяются в единое полотно, однако поведение осей и шкал может как наследоваться, так и быть переопределено через механизм разрешения конфликтов (resolve).


Механика layer и совмещение визуальных слоёв

Конструкция layer позволяет комбинировать несколько визуальных представлений в одном графике:

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

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

{
  "data": { "url": "data.csv" },
  "layer": [
    {
      "mark": "line",
      "encoding": {
        "x": { "field": "date", "type": "temporal" },
        "y": { "field": "valueA", "type": "quantitative" }
      }
    },
    {
      "mark": "line",
      "encoding": {
        "x": { "field": "date", "type": "temporal" },
        "y": { "field": "valueB", "type": "quantitative" }
      }
    }
  ]
}

В таком виде оба ряда отображаются в одной системе координат, что приводит к автоматическому масштабированию по объединённому диапазону значений.


Шкалы в Vega-Lite и проблема общей системы координат

Система шкал Vega-Lite строится вокруг принципа автоматического вывода домена (domain) и диапазона (range) на основе всех задействованных слоёв. Для оси y это означает:

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

Такой подход эффективен при сопоставимых величинах, но приводит к искажению формы данных при различии порядков:

  • температура (0–40)
  • финансовые показатели (0–1 000 000)
  • проценты (0–1)

В результате малые значения становятся визуально неразличимыми.


Независимые оси через resolve.scale

Механизм resolve позволяет переопределить поведение шкал для каждого канала. Для задачи двойных осей используется настройка независимости по y:

{
  "data": { "url": "data.csv" },
  "layer": [
    {
      "mark": "line",
      "encoding": {
        "x": { "field": "date", "type": "temporal" },
        "y": { "field": "temperature", "type": "quantitative" }
      }
    },
    {
      "mark": "line",
      "encoding": {
        "x": { "field": "date", "type": "temporal" },
        "y": { "field": "sales", "type": "quantitative" }
      }
    }
  ],
  "resolve": {
    "scale": {
      "y": "independent"
    }
  }
}

При таком подходе Vega-Lite создаёт:

  • две независимые шкалы по оси Y
  • две оси значений на одном графике
  • общую ось X (если не переопределено)

Поведение осей при независимых шкалах

При включении y: "independent" каждая шкала получает собственный:

  • domain (диапазон значений)
  • ticks (деления)
  • форматирование значений
  • подписи оси

Однако ось X остаётся общей, если не задано:

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

Это формирует типичную структуру двойной оси:

  • левая ось — первая метрика
  • правая ось — вторая метрика

Пример: временной ряд и финансовый показатель

{
  "data": { "url": "metrics.csv" },
  "layer": [
    {
      "mark": { "type": "line", "color": "#1f77b4" },
      "encoding": {
        "x": { "field": "month", "type": "temporal" },
        "y": {
          "field": "temperature",
          "type": "quantitative",
          "axis": { "title": "Температура" }
        }
      }
    },
    {
      "mark": { "type": "line", "color": "#d62728" },
      "encoding": {
        "x": { "field": "month", "type": "temporal" },
        "y": {
          "field": "revenue",
          "type": "quantitative",
          "axis": { "title": "Выручка" }
        }
      }
    }
  ],
  "resolve": {
    "scale": {
      "y": "independent"
    }
  }
}

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


Конфликты encoding и роль цветового кодирования

При использовании нескольких слоёв возникает проблема идентификации рядов. Vega-Lite не автоматически связывает независимые оси с легендой, если encoding не задан явно.

Типовые решения:

  • назначение color в каждом слое
  • использование strokeDash для различения линий
  • явное задание legend

Пример:

"encoding": {
  "color": { "value": "#1f77b4" }
}

или через поле:

"color": { "field": "series", "type": "nominal" }

При независимых шкалах важно учитывать, что легенда не отражает различие осей, а только визуальные серии.


Синхронизация по X и независимость Y

Наиболее распространённый сценарий двойных осей основан на жёсткой синхронизации временной оси:

  • x: shared temporal scale
  • y: independent quantitative scales

Такое разделение позволяет:

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

При этом любые трансформации данных (transform) применяются до разбиения на слои, что обеспечивает согласованность временных точек.


Расширенные сценарии многослойных осей

Нормализация одной из шкал

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

  • z-score
  • min-max scaling
  • процент от базового значения

Это позволяет использовать shared scale, но сохранять читаемость трендов.


Тройные и более осевые композиции

Vega-Lite допускает расширение через дополнительные слои:

"resolve": {
  "scale": {
    "y": "independent"
  }
}

Каждый новый слой автоматически получает собственную шкалу, что приводит к множественным осям. Однако визуальная интерпретация становится ограниченной из-за перегрузки координатной системы.


Комбинация line + area на независимых шкалах

Слойная модель позволяет сочетать различные mark-типы:

  • line для тренда
  • area для накопленных значений
  • bar для дискретных величин

При независимых шкалах каждый тип сохраняет собственную интерпретацию диапазона.


Ограничения модели независимых шкал

Использование y: "independent" в resolve.scale приводит к ряду структурных последствий:

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

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