Логарифмический масштаб: d3.scaleLog()

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


Принцип логарифмического преобразования

Логарифмический масштаб основан на преобразовании значений через логарифм:

[ y = _b(x)]

где (b) — основание логарифма (обычно 10 или e), а (x) — исходное значение данных.

В контексте визуализации это означает, что равные расстояния на оси соответствуют не равным приращениям данных, а равным отношениям.

Ключевой эффект:

  • разница между 1 и 10 визуально такая же, как между 10 и 100
  • масштабирование работает с мультипликативными изменениями, а не аддитивными

d3.scaleLog(): базовая структура

Логарифмическая шкала создаётся через:

const scale = d3.scaleLog();

Далее задаются:

  • domain — входной диапазон данных
  • range — выходной диапазон (например, пиксели)
  • base — основание логарифма (по умолчанию 10)

Пример:

const scale = d3.scaleLog()
  .domain([1, 1000])
  .range([0, 300]);

Это означает:

  • значение 1 → 0 px
  • значение 10 → ~100 px
  • значение 100 → ~200 px
  • значение 1000 → 300 px

Требования к domain

Логарифмическая шкала имеет строгие ограничения:

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

Причина: логарифм от 0 и отрицательных чисел не определён в вещественной области

Пример корректного диапазона:

.domain([0.1, 1000])

Пример некорректного диапазона:

.domain([-10, 100]) // ошибка логики шкалы

Выбор основания логарифма

Основание влияет на визуальное восприятие распределения:

const scale10 = d3.scaleLog().base(10);
const scaleE  = d3.scaleLog().base(Math.E);

Практические особенности:

  • base 10 — более интуитивен для финансовых и научных графиков
  • base e — используется в моделировании роста и экспоненциальных процессов
  • выбор базы не меняет порядок данных, только “растяжение” шкалы

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

Функция преобразования:

scale(10); // возвращает позицию в range

Пример:

const scale = d3.scaleLog()
  .domain([1, 100])
  .range([0, 500]);

scale(1);   // 0
scale(10);  // ~250
scale(100); // 500

Интерполяция происходит через:

[ f(x) = ]

где (a) и (b) — границы domain.


Обратное преобразование (invert)

Логарифмическая шкала поддерживает обратное преобразование:

scale.invert(250);

Это позволяет:

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

Нормализация и сглаживание данных

Логарифмический масштаб используется для:

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

Пример данных:

[1, 5, 10, 100, 1000, 10000]

На линейной шкале:

  • большая часть точек “сжимается” в начале

На логарифмической:

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

Работа с осью d3.axisLog()

Для визуализации шкалы используется ось:

const xAxis = d3.axisBottom(scale);

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

  • 1, 10, 100, 1000
  • промежуточные значения могут быть скрыты

Дополнительная настройка:

d3.axisBottom(scale)
  .ticks(10, ",.1s");

Настройка делений (ticks)

Логарифмическая шкала имеет особенности генерации ticks:

scale.ticks(5);

Особенности:

  • ticks распределяются по степеням основания
  • неравномерное визуальное расстояние
  • D3 старается выбирать “чистые” значения

Можно задать формат:

d3.axisBottom(scale)
  .tickFormat(d3.format(".0s"));

Поведение с небольшими значениями

При значениях близких к нулю логарифмическая шкала становится чувствительной:

  • 0.1 → 10⁻¹
  • 0.01 → 10⁻²
  • 0.001 → 10⁻³

Практическая особенность:

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

Клэмпинг значений

Логарифмическая шкала может ограничивать выход за domain:

scale.clamp(true);

Поведение:

  • значения меньше minimum → фиксируются на минимуме range
  • значения больше maximum → фиксируются на максимуме range

Это полезно для:

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

Сравнение с линейной шкалой

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

[ y = ax + b]

Логарифмическая:

[ y = (x)]

Различие поведения:

  • линейная отображает абсолютные изменения
  • логарифмическая отображает относительные изменения

Пример:

  • рост с 1 до 10 = ×10
  • рост с 10 до 100 = ×10

Обе ситуации равны на логарифмической шкале, но различны на линейной.


Практическое применение

Логарифмический масштаб применяется в случаях:

  • финансовые графики (цены акций, капитализация)
  • анализ населения и демографии
  • частотный анализ (спектры, аудио)
  • научные измерения (pH, децибелы)
  • машинное обучение (loss curves с экспоненциальным спадом)

Комбинирование с другими шкалами

В D3 возможно комбинирование:

const x = d3.scaleLog().domain([1, 1000]).range([0, width]);
const y = d3.scaleLinear().domain([0, 100]).range([height, 0]);

Типичный сценарий:

  • X — логарифмический (время, масштаб роста)
  • Y — линейный (значение метрики)

Интерактивные особенности

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

  • обратное преобразование через invert
  • обработку drag/zoom событий
  • пересчёт координат в реальном времени

Пример:

svg.on("click", (event) => {
  const xValue = scale.invert(d3.pointer(event)[0]);
});

Особенности производительности

Логарифмическая шкала:

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

Основная нагрузка возникает не в scaleLog, а в рендеринге DOM/SVG элементов.


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

  • включение нуля в domain
  • смешивание отрицательных значений
  • выбор слишком узкого диапазона (например, [9, 11])
  • игнорирование логики интерпретации данных
  • использование логарифмической шкалы там, где данные линейны

Визуальная интерпретация распределений

Логарифмическая шкала фактически выполняет роль “выпрямления” экспоненциальных кривых:

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

Это делает возможным анализ данных, которые в линейной шкале выглядят “сплющенными” или перегруженными в одной области.