Цвет, палитры и доступность
Цвет — мощный канал и частый источник ошибок. Радуга для чисел и красно-зелёный для дальтоников — классические провалы.
«Цвет должен нести смысл. Если он не кодирует данные и не направляет внимание — это визуальный шум».
Правильная палитра зависит от типа данных. Есть три семейства: sequential (последовательные) — для упорядоченных величин от малого к большому; diverging (расходящиеся) — для данных с осмысленным центром (корреляции, отклонения от нормы); qualitative (категориальные) — для несвязанных категорий.
Почему нельзя просто «выбрать красивые цвета»? Потому что цвет — это канал кодирования данных ровно так же, как длина или позиция, и его форма должна соответствовать структуре данных. Категориальная палитра, применённая к упорядоченной величине, заставляет глаз искать порядок там, где цвета его не несут (красный «больше» жёлтого или нет?). И наоборот: непрерывный градиент, наложенный на несвязанные категории, ложно намекает, что «синий» регион ближе к «голубому», чем к «оранжевому». Несовпадение типа палитры с типом данных — это не вопрос эстетики, а прямая дезинформация на уровне восприятия.
Отдельно стоит сказать про доступность, потому что её часто считают «приятным бонусом», а на самом деле это требование корректности. Около 8% мужчин и 0,5% женщин имеют ту или иную форму цветовой слепоты, чаще всего красно-зелёную (дейтеранопию или протанопию). Если ваш единственный различающий признак — красный против зелёного, для этой аудитории график буквально нечитаем: «прибыль» и «убыток» сливаются. Поэтому цвет почти никогда не должен быть единственным каналом — его дублируют формой маркера, штриховкой, прямой подписью или порядком. Проверить, как график выглядит для дальтоника, можно симуляторами вроде Color Oracle или встроенными фильтрами браузерных DevTools.
ВЫБОР ПАЛИТРЫ ПО ТИПУ ДАННЫХ
Данные упорядочены? --- нет --> qualitative (категории)
|
да
|
Есть смысловой центр (0, норма)? --- да --> diverging
|
нет
|
sequential (светлое -> тёмное)
import seaborn as sns
# sequential — для величин (рост, цена)
sns.heatmap(data, cmap="viridis") # перцептивно равномерная
# diverging — для отклонений и корреляций
sns.heatmap(corr, cmap="coolwarm", center=0)
# qualitative — для категорий
sns.scatterplot(data=df, x="x", y="y", hue="group", palette="Set2")
viridis — современный стандарт: перцептивно равномерная (равные шаги данных = равные шаги цвета) и читаемая дальтониками, в отличие от старой радуги jet.
Как работает под капотом
Colormap — это функция «нормализованное значение [0,1] → цвет». Радуга (jet) нелинейна по светлоте: создаёт ложные границы и тёмные/яркие полосы там, где данные меняются плавно. Viridis монотонно растёт по светлоте, поэтому даже в оттенках серого (или для дальтоника) порядок сохраняется. Доступность проверяют по контрасту WCAG: отношение яркостей текста и фона ≥ 4.5:1.
Посчитаем контраст WCAG вручную — это число решает, прочитают ли подпись.
# Контраст WCAG: отношение яркостей. Нужно >= 4.5:1 для текста
def luminance(r, g, b):
def chan(c):
c = c / 255
return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
R, G, B = chan(r), chan(g), chan(b)
return 0.2126 * R + 0.7152 * G + 0.0722 * B
def contrast(c1, c2):
l1, l2 = luminance(*c1), luminance(*c2)
hi, lo = max(l1, l2), min(l1, l2)
return (hi + 0.05) / (lo + 0.05)
text = (90, 90, 90) # серый текст
bg = (255, 255, 255) # белый фон
ratio = contrast(text, bg)
print("Контраст: {:.2f} : 1".format(ratio))
print("Проходит для текста?" , ratio >= 4.5)
«Попробуй сам ▶» — затемните текст и контраст вырастет. Светло-серая подпись на белом часто проваливает порог 4.5:1.
Частые ошибки
Радуга (jet) для непрерывных данных — ложные границы. Красно-зелёное кодирование — невидимо для ~8% мужчин-дальтоников. Слишком много категориальных цветов (более 7–8) — неразличимы. Цвет как единственный канал — добавьте форму или подпись. Низкий контраст подписей.
Ещё несколько ловушек, которые встречаются постоянно. Не-перцептивно-равномерный градиент: даже без радуги градиент может быть нелинейным по светлоте, и тогда равные шаги данных дают неравные на вид шаги цвета — глаз «видит» резкий скачок там, где значение меняется плавно; именно для этого придуманы viridis, magma, cividis. Перенасыщенные «кричащие» цвета: заливка чистым насыщенным красным или ядовито-зелёным утомляет глаз и затрудняет длительное чтение; для больших площадей берут приглушённые тона, а яркий цвет приберегают для акцента на одной важной серии.
И про типографику, без которой палитра бесполезна. Подписи мельче 9–10 пунктов на графике для проектора или мобильного экрана физически нечитаемы — размер шрифта подбирают под канал просмотра, а не под то, как удобно в редакторе. Поворот подписей оси на 90° вертикально заставляет читателя крутить голову; длинные категории лучше развернуть горизонтально, сократить или поменять оси местами (горизонтальный bar). Контраст не только для текста, но и для самих данных: бледная серия на белом фоне может пройти порог для глаза человека, но потеряться при печати или на тусклом проекторе — проверяйте контраст не только подписей, но и ключевых линий.
Best practices
- Sequential для величин, diverging для отклонений, qualitative для категорий.
- Предпочитайте перцептивно равномерные палитры (viridis и родственные).
- Дублируйте цвет формой/подписью — для дальтоников.
- Проверяйте контраст текста: ≥ 4.5:1.
- Не более 7–8 категориальных цветов.
Итог: цвет под контролем. В финальном уроке соберём всё в чеклист сторителлинга данными.