Квантование в визуализации данных применяется для преобразования
непрерывных или высокоразмерных значений в дискретные категории. В D3.js
для этого используются два ключевых механизма:
scaleQuantize и scaleQuantile. Несмотря на
схожую цель — разбиение числового диапазона на классы — их поведение
принципиально различается.
Квантовая шкала scaleQuantize выполняет разбиение
непрерывного входного диапазона на равные интервалы и сопоставляет
каждому интервалу фиксированное выходное значение.
Формально:
const scale = d3.scaleQuantize()
.domain([0, 100])
.range(["low", "medium", "high"]);
Здесь диапазон [0, 100] делится на три равные части:
Количество интервалов определяется длиной range. Если в
range три элемента, создаётся три равных сегмента.
Каждый входной элемент преобразуется через линейное разбиение:
где n — количество значений в range.
const colorScale = d3.scaleQuantize()
.domain([0, 1000])
.range(["#d4eeff", "#74c0fc", "#1c7ed6"]);
console.log(colorScale(100)); // светлый цвет
console.log(colorScale(500)); // средний
console.log(colorScale(900)); // тёмный
Границы интервалов вычисляются автоматически и равномерно. Это приводит к следующему эффекту:
scaleQuantile решает другую задачу: разбиение данных по
квантилям, то есть по фактическому распределению значений.
В отличие от scaleQuantize, здесь:
Квантильная шкала стремится распределить данные так, чтобы:
Это делает её особенно полезной для анализа распределений с перекосами.
const scale = d3.scaleQuantile()
.domain([10, 20, 30, 40, 50, 60, 70, 80])
.range(["Q1", "Q2", "Q3"]);
Здесь данные автоматически делятся на три группы:
Процесс включает:
Формально:
n — количество элементов, а k — число
квантилей,n / k значенийscaleQuantize:
scaleQuantile:
scaleQuantize чувствителен к выбросам, так как
расширяет общий диапазонscaleQuantile устойчив, так как работает с порядковыми
позициямиДля цветового кодирования плотности значений часто используется квантование:
const color = d3.scaleQuantile()
.domain(dataset)
.range(d3.schemeBlues[5]);
Такой подход обеспечивает равномерное распределение цветов по количеству наблюдений, а не по диапазону значений.
const data = [5, 7, 12, 18, 22, 29, 35, 42, 55, 60, 75, 90];
const q = d3.scaleQuantize()
.domain([5, 90])
.range(["A", "B", "C"]);
data.map(d => q(d));
Результат зависит только от позиции числа в диапазоне, а не от плотности распределения.
const ql = d3.scaleQuantile()
.domain(data)
.range(["A", "B", "C"]);
data.map(d => ql(d));
Результат зависит от относительного положения элемента в отсортированном массиве.
После инициализации шкала вычисляет пороговые значения:
scaleQuantile()
.domain(data)
.range(["low", "mid", "high"]);
console.log(scale.quantiles());
Метод quantiles() возвращает массив порогов,
например:
[20, 45, 70]
Эти значения разделяют пространство на квантили.
Квантование напрямую влияет на восприятие графиков:
scaleQuantize создаёт геометрически равные сегменты, но
может искажать восприятие плотностиscaleQuantile сохраняет статистическую справедливость
распределения, но искажает интервалы значенийКвантовые шкалы занимают промежуточное положение между:
scaleLinear — непрерывная шкалаscaleThreshold — ручное задание границscaleQuantize / scaleQuantile —
автоматическая дискретизацияscaleThreshold позволяет задать пороги вручную:
d3.scaleThreshold()
.domain([10, 50, 100])
.range(["A", "B", "C", "D"]);
Часто квантильные шкалы используются вместе с палитрами D3:
d3.scaleQuantile()
.domain(data)
.range(d3.schemeRdYlBu[5]);
Такой подход обеспечивает согласованное визуальное распределение цветовых классов.
При малом числе элементов:
scaleQuantile может давать менее точные квантильные
границыscaleQuantize сохраняет предсказуемость, но теряет
смысл статистической группировкиscaleQuantize не зависит от порядка данныхscaleQuantile требует сортировки и полностью опирается
на порядок значенийОбе шкалы возвращают дискретные категории, но интерпретация различается:
scaleQuantize категория — функция положения на
числовой осиscaleQuantile категория — функция ранга в
распределении