Восприятие и кодирование данных
Глаз сравнивает длины точно, а площади и углы — плохо. Это закон, а не мнение.
«Любой график — это кодирование чисел в визуальные признаки. Качество графика определяется тем, насколько точно зритель сможет их раскодировать».
Когда вы строите график, вы кодируете число в визуальный канал: длину столбика, позицию точки, угол сектора, площадь круга, насыщенность цвета. Кливленд и МакГилл экспериментально измерили, насколько точно люди декодируют каждый канал. Результат — иерархия точности.
ТОЧНОСТЬ ДЕКОДИРОВАНИЯ (от высокой к низкой)
высокая
^ положение на общей шкале <- scatter, bar
| положение на разных шкалах
| длина / направление
| угол / наклон <- pie
| площадь <- bubble
| объём / кривизна
низкая оттенок / насыщенность <- heatmap
Отсюда практический вывод: то, что важно сравнить точно, кодируйте позицией или длиной. То, что второстепенно — цветом. Поэтому bar (длина) бьёт pie (угол) почти всегда.
Эта иерархия — не абстрактная теория, а практический фильтр при проектировании каждого графика. Спросите себя: «какое сравнение в этих данных самое важное?» — и отдайте под него самый точный канал. Если читателю критично понять, что продукт A продаётся ровно на 12% лучше продукта B, кодируйте это длиной столбиков на общей оси, а не размером пузырьков и не оттенком. Цвет и площадь приберегите для вторичных измерений, где достаточно качественного «больше/меньше». Так один и тот же датасет можно подать честно или обманчиво, не меняя ни одного числа — меняя лишь то, какой канал несёт главную мысль.
Важно и то, что каналы не равноценны по числу различимых уровней. Глаз надёжно различает лишь 5–7 ступеней насыщенности и не более десятка категориальных цветов, прежде чем они начинают путаться; зато по позиции на оси он различает сотни уровней. Поэтому непрерывную величину с большим диапазоном бессмысленно кодировать только цветом — теряется разрешение. А категориальную переменную с двадцатью значениями нельзя честно показать двадцатью цветами: половина сольётся. В таких случаях прибегают к фасетингу (small multiples) — разбивают данные на сетку маленьких графиков, перенося часть нагрузки с цвета на позицию.
Как работает под капотом
Преаттентивные признаки — цвет, ориентация, размер — обрабатываются параллельно за ~200 мс. Поэтому одна красная точка среди синих «выпрыгивает» сама. Но точное сравнение требует усилия: глаз отлично говорит «этот столбик выше», но плохо — «этот сектор на 7% больше».
Нормализация — частый шаг перед кодированием цветом: переводим числа в диапазон 0..1, чтобы сопоставить им интенсивность.
# Min-max нормализация: число -> позиция на шкале 0..1 (как для цвета)
values = [120, 340, 200, 90, 410, 260]
lo, hi = min(values), max(values)
norm = [(v - lo) / (hi - lo) for v in values]
for v, x in zip(values, norm):
blocks = int(round(x * 20))
print("{:>4} | {:.2f} | {}".format(v, x, "#" * blocks))
«Попробуй сам ▶» — это ровно то, что делает colormap: сопоставляет нормализованному значению интенсивность. Понимая нормализацию, вы не удивитесь, почему один выброс «съедает» всю цветовую шкалу heatmap.
Частые ошибки
Кодировать важное цветом, а не длиной. Использовать площадь круга для точного сравнения (глаз недооценивает площади). Радужная палитра (jet) для непрерывных данных — она создаёт ложные «границы» там, где их нет.
Добавим частые ловушки восприятия. Кодировать величину диаметром круга вместо площади: если радиус пропорционален значению, площадь растёт как квадрат, и величины выглядят преувеличенными в разы — диаметр и площадь нельзя путать. Игнорировать дальтонизм: красно-зелёная пара неразличима примерно для 8% мужчин, поэтому статусы «хорошо/плохо» нельзя кодировать только этими цветами — добавляйте форму или подпись. Использовать неупорядоченную (qualitative) палитру для упорядоченной величины: зритель не поймёт, какой цвет «больше». И обратная ошибка — последовательная палитра для категорий без порядка: она навяжет ложную идею ранжирования там, где его нет. Наконец, расходящаяся (diverging) палитра без осмысленного центра (нуля или среднего) сбивает с толку: её середина должна что-то значить.
Best practices
- Главное сравнение — позицией или длиной.
- Для непрерывных величин — последовательные (sequential) палитры, не радуга.
- Цвет — для категорий и акцентов, не для точных чисел.
Итог: теперь вы знаете, почему одни графики «читаются», а другие — нет. Эта иерархия будет с нами весь курс. Переходим к практике — Matplotlib.