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

Линейная шкала (linear scale) — один из базовых механизмов преобразования данных в Vega и Vega-Lite. Она используется для отображения количественных значений в непрерывный визуальный диапазон: координаты, размеры, прозрачность, цвет, толщина линий и другие визуальные параметры.

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

Тип шкалы:

{
  "scale": {
    "type": "linear"
  }
}

Принцип работы линейной шкалы

Линейная шкала содержит два ключевых понятия:

  • domain — диапазон входных данных;
  • range — диапазон визуального представления.

Простейшая схема:

domain: [0, 100]
range:  [0, 500]

В таком случае:

Значение Результат
0 0
50 250
100 500

Формула линейного преобразования:

[ y = a x + b]

Где:

  • x — исходное значение;
  • y — визуальное значение;
  • a — коэффициент масштабирования;
  • b — смещение.

Для линейной зависимости:

genui{“math_block_widget_always_prefetch_v2”:{“content”:“y=ax+b”}}


Линейная шкала в Vega-Lite

Базовый пример

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "data": {
    "values": [
      {"x": 10, "y": 20},
      {"x": 20, "y": 35},
      {"x": 30, "y": 50},
      {"x": 40, "y": 70}
    ]
  },

  "mark": "point",

  "encoding": {
    "x": {
      "field": "x",
      "type": "quantitative",
      "scale": {
        "type": "linear"
      }
    },

    "y": {
      "field": "y",
      "type": "quantitative",
      "scale": {
        "type": "linear"
      }
    }
  }
}

Здесь обе оси используют линейное масштабирование. Vega-Lite автоматически вычисляет:

  • минимальные значения;
  • максимальные значения;
  • шаги делений;
  • подписи осей.

Автоматическое определение domain

По умолчанию Vega-Lite анализирует данные и вычисляет границы автоматически.

Например:

"scale": {
  "type": "linear"
}

Если значения поля:

[12, 18, 22, 47]

то domain автоматически станет:

[12, 47]

Такое поведение удобно для динамических графиков и потоковых данных.


Явное указание domain

Иногда требуется фиксированный диапазон.

"scale": {
  "type": "linear",
  "domain": [0, 100]
}

Теперь независимо от данных шкала всегда будет использовать диапазон от 0 до 100.

Это особенно важно:

  • при сравнении нескольких графиков;
  • при анимациях;
  • при обновлении данных;
  • при работе с dashboard-интерфейсами.

Использование range

range определяет визуальный диапазон.

Для координат:

"range": [0, 400]

Для цвета:

"range": ["white", "red"]

Для размера:

"range": [10, 500]

Линейная цветовая шкала

Интерполяция цветов

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

Пример:

{
  "mark": "circle",

  "encoding": {
    "color": {
      "field": "temperature",
      "type": "quantitative",

      "scale": {
        "type": "linear",
        "domain": [0, 100],
        "range": ["blue", "red"]
      }
    }
  }
}

Значения будут интерполироваться:

Значение Цвет
0 Синий
50 Фиолетовый
100 Красный

Цветовые схемы

Вместо range можно использовать scheme.

"scale": {
  "scheme": "viridis"
}

Популярные схемы:

Scheme Назначение
viridis Универсальная
plasma Яркие градиенты
inferno Тёмные тепловые карты
magma Контрастные переходы
blues Монохромный синий
reds Монохромный красный

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

В Vega шкалы задаются отдельно в массиве scales.

Пример

{
  "scales": [
    {
      "name": "xscale",

      "type": "linear",

      "domain": [0, 100],

      "range": [0, 500]
    }
  ]
}

Использование шкалы:

{
  "encode": {
    "update": {
      "x": {
        "scale": "xscale",
        "field": "value"
      }
    }
  }
}

Свойство zero

Привязка к нулю

По умолчанию количественные шкалы часто включают 0.

"scale": {
  "zero": true
}

Это особенно важно:

  • для bar chart;
  • column chart;
  • area chart.

Без нуля визуальная интерпретация может искажаться.


Отключение zero

"scale": {
  "zero": false
}

Пример использования:

  • финансовые графики;
  • точные научные измерения;
  • временные ряды с малыми колебаниями.

Свойство nice

Округление границ

nice делает границы шкалы «красивыми».

Без nice:

[3, 97]

С nice:

[0, 100]

Пример:

"scale": {
  "nice": true
}

Настройка количества делений

"scale": {
  "nice": 5
}

Vega пытается подобрать удобные интервалы для пяти основных делений.


Свойство clamp

Ограничение значений

clamp запрещает выход за пределы диапазона.

Пример:

"scale": {
  "domain": [0, 100],
  "range": [0, 500],
  "clamp": true
}

Теперь:

Значение Результат
-20 0
50 250
120 500

Поведение без clamp

Если clamp: false, значения продолжают вычисляться линейно за пределами диапазона.

Например:

Значение Результат
120 600
150 750

Это полезно:

  • для анимаций;
  • при вычислении выходов за границы;
  • для zoom/pan систем.

Свойство round

Округление пикселей

"scale": {
  "round": true
}

Значения координат округляются до целых пикселей.

Преимущества:

  • более чёткие линии;
  • отсутствие размытия;
  • улучшение отображения на canvas.

Обратная шкала

reverse

Инверсия диапазона:

"scale": {
  "reverse": true
}

Пример:

domain: [0, 100]
range: [500, 0]

Используется:

  • для инверсии осей;
  • вертикальных heatmap;
  • специальных систем координат.

Интерполяция значений

Линейная шкала строится на интерполяции.

Формула:

genui{“math_block_widget_always_prefetch_v2”:{“content”:“y=r_0+”}}

Где:

  • d0, d1 — domain;
  • r0, r1 — range;
  • x — входное значение.

Работа с отрицательными значениями

Линейная шкала полностью поддерживает отрицательные числа.

Пример:

"domain": [-100, 100]

Использование:

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

Пример графика

{
  "mark": "line",

  "encoding": {
    "x": {
      "field": "time",
      "type": "quantitative"
    },

    "y": {
      "field": "delta",
      "type": "quantitative",

      "scale": {
        "domain": [-50, 50]
      }
    }
  }
}

Многоточечный domain

Piecewise scale

Линейная шкала может иметь несколько сегментов.

"scale": {
  "domain": [0, 50, 100],
  "range": ["blue", "yellow", "red"]
}

Поведение:

Значение Цвет
0 Синий
50 Жёлтый
100 Красный

Это позволяет строить:

  • diverging color scale;
  • сложные тепловые карты;
  • нелинейные визуальные переходы.

Связывание шкалы с шириной контейнера

В Vega:

{
  "range": "width"
}

Или:

{
  "range": "height"
}

Пример:

{
  "scales": [
    {
      "name": "xscale",
      "type": "linear",
      "domain": [0, 100],
      "range": "width"
    }
  ]
}

Шкала автоматически адаптируется к размеру контейнера.


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

Генерация tick-значений

Линейные шкалы автоматически создают деления осей.

"axis": {
  "tickCount": 10
}

Форматирование подписей

"axis": {
  "format": ".2f"
}

Пример:

Значение Отображение
1 1.00
2.5 2.50

Процентный формат

"axis": {
  "format": "%"
}

Масштабирование размеров

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

Размер кругов

{
  "mark": "circle",

  "encoding": {
    "size": {
      "field": "population",
      "type": "quantitative",

      "scale": {
        "range": [10, 1000]
      }
    }
  }
}

Масштабирование прозрачности

{
  "encoding": {
    "opacity": {
      "field": "density",
      "type": "quantitative",

      "scale": {
        "domain": [0, 1],
        "range": [0.1, 1]
      }
    }
  }
}

Масштабирование толщины линий

{
  "encoding": {
    "strokeWidth": {
      "field": "weight",
      "type": "quantitative",

      "scale": {
        "range": [1, 10]
      }
    }
  }
}

Отличие от других шкал

Шкала Назначение
linear Линейные данные
log Логарифмические зависимости
pow Степенное преобразование
sqrt Квадратный корень
symlog Смешанные логарифмические данные
time Даты и время
ordinal Категории
band Категориальные интервалы

Когда использовать linear

Линейная шкала подходит, если:

  • данные распределены равномерно;
  • важны пропорции;
  • отсутствуют экстремальные порядки величин;
  • требуется интуитивное отображение.

Когда linear использовать нежелательно

Линейная шкала плохо подходит для:

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

В таких случаях лучше использовать:

  • log;
  • symlog;
  • pow.

Практический пример полного графика

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "width": 700,
  "height": 400,

  "data": {
    "values": [
      {"year": 2019, "sales": 120},
      {"year": 2020, "sales": 180},
      {"year": 2021, "sales": 240},
      {"year": 2022, "sales": 310},
      {"year": 2023, "sales": 460}
    ]
  },

  "mark": {
    "type": "line",
    "point": true
  },

  "encoding": {
    "x": {
      "field": "year",
      "type": "quantitative",

      "scale": {
        "type": "linear"
      },

      "axis": {
        "tickCount": 5
      }
    },

    "y": {
      "field": "sales",
      "type": "quantitative",

      "scale": {
        "type": "linear",
        "domain": [0, 500],
        "nice": true,
        "zero": true
      },

      "axis": {
        "tickCount": 10
      }
    }
  }
}

Внутреннее устройство linear scale в Vega

При создании линейной шкалы Vega:

  1. Анализирует domain.
  2. Вычисляет коэффициент масштабирования.
  3. Создаёт функцию преобразования.
  4. Генерирует ticks.
  5. Применяет интерполяцию.
  6. Выполняет преобразование при каждом рендеринге.

Упрощённо:

function scale(x) {
  return r0 + (x - d0) * k;
}

Где:

k = (r1 - r0) / (d1 - d0)

Производительность

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

Причины:

  • простая арифметика;
  • отсутствие сложных преобразований;
  • минимальные вычисления;
  • высокая оптимизация в d3-scale.

Поэтому linear используется по умолчанию для большинства количественных данных.


Особенности Vega-Lite

В Vega-Lite тип шкалы часто определяется автоматически.

Например:

"type": "quantitative"

обычно приводит к:

"scale": {
  "type": "linear"
}

Явное указание требуется редко, но полезно:

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

Совместимость с D3

Vega и Vega-Lite используют механизм масштабирования из D3.

Основа:

d3.scaleLinear()

Поэтому многие свойства полностью совпадают:

  • domain;
  • range;
  • clamp;
  • nice;
  • interpolate;
  • ticks.

Это упрощает переход между D3 и Vega.