Данные и аналитика
anthropics/data-visualization
Создаёт визуализации данных с помощью Python (matplotlib, seaborn, plotly), помогает выбрать подходящий тип графика и оформить его с учётом дизайна и доступности. Полезно при анализе данных, подготовке отчётов и презентаций для наглядного представления информации.
Оцените навык первым
SKILL.md
Перевод инструкции, которую получает агент при подключении навыка. Агент всегда использует оригинал.
Навык Визуализации Данных
Руководство по выбору диаграмм, шаблоны кода визуализации на Python, принципы дизайна и аспекты доступности для создания эффективных визуализаций данных.
Руководство по Выбору Диаграмм
Выбор по Типу Взаимосвязи Данных
| Что Вы Показываете | Лучшая Диаграмма | Альтернативы |
|---|---|---|
| Тренд во времени | Линейный график | Площадная диаграмма (если показывается накопление или состав) |
| Сравнение по категориям | Вертикальная столбчатая диаграмма | Горизонтальная столбчатая (много категорий), диаграмма с палочками (lollipop) |
| Ранжирование | Горизонтальная столбчатая диаграмма | Точечный график, наклонная диаграмма (сравнение двух периодов) |
| Часть от целого | Сложенная столбчатая диаграмма | Древовидная карта (иерархическая), вафельная диаграмма |
| Состав во времени | Сложенная площадная диаграмма | 100% сложенная столбчатая (для акцента на пропорциях) |
| Распределение | Гистограмма | Ящичная диаграмма (сравнение групп), скрипичная диаграмма, точечный график |
| Корреляция (2 переменные) | Точечный график | Пузырьковая диаграмма (добавить 3-ю переменную размером) |
| Корреляция (много переменных) | Тепловая карта (матрица корреляций) | Парный график |
| Географические паттерны | Хороплетная карта | Пузырьковая карта, шестиугольная карта |
| Поток / процесс | Диаграмма Санки | Воронкообразная диаграмма (последовательные этапы) |
| Сеть взаимосвязей | Граф сети | Хордовая диаграмма |
| Результаты vs. цель | Буллет-диаграмма | Индикатор (только один KPI) |
| Несколько KPI одновременно | Малые множества | Дашборд с отдельными диаграммами |
Когда НЕ использовать определённые диаграммы
- Круговые диаграммы: Избегайте, если категорий больше 6 и точные пропорции менее важны, чем приблизительное сравнение. Люди плохо сравнивают углы. Используйте столбчатые диаграммы.
- 3D диаграммы: Никогда. Они искажают восприятие и не добавляют информации.
- Диаграммы с двумя осями: Используйте с осторожностью. Могут вводить в заблуждение, создавая иллюзию корреляции. Если используете, чётко подписывайте обе оси.
- Сложенные столбчатые (много категорий): Трудно сравнивать средние сегменты. Используйте малые множества или сгруппированные столбцы.
- Пончиковые диаграммы: Немного лучше круговых, но имеют те же основные проблемы. Используйте максимум для отображения одного KPI.
Шаблоны Кода Визуализации на Python
Настройка и Стиль
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import seaborn as sns
import pandas as pd
import numpy as np
# Профессиональная настройка стиля
plt.style.use('seaborn-v0_8-whitegrid')
plt.rcParams.update({
'figure.figsize': (10, 6),
'figure.dpi': 150,
'font.size': 11,
'axes.titlesize': 14,
'axes.titleweight': 'bold',
'axes.labelsize': 11,
'xtick.labelsize': 10,
'ytick.labelsize': 10,
'legend.fontsize': 10,
'figure.titlesize': 16,
})
# Палитры, удобные для дальтоников
PALETTE_CATEGORICAL = ['#4C72B0', '#DD8452', '#55A868', '#C44E52', '#8172B3', '#937860']
PALETTE_SEQUENTIAL = 'YlOrRd'
PALETTE_DIVERGING = 'RdBu_r'
Линейный График (Временной Ряд)
fig, ax = plt.subplots(figsize=(10, 6))
for label, group in df.groupby('category'):
ax.plot(group['date'], group['value'], label=label, linewidth=2)
ax.set_title('Тренд Метрики по Категориям', fontweight='bold')
ax.set_xlabel('Дата')
ax.set_ylabel('Значение')
ax.legend(loc='upper left', frameon=True)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# Форматирование дат по оси x
fig.autofmt_xdate()
plt.tight_layout()
plt.savefig('trend_chart.png', dpi=150, bbox_inches='tight')
Столбчатая Диаграмма (Сравнение)
fig, ax = plt.subplots(figsize=(10, 6))
# Сортировка по значению для удобства чтения
df_sorted = df.sort_values('metric', ascending=True)
bars = ax.barh(df_sorted['category'], df_sorted['metric'], color=PALETTE_CATEGORICAL[0])
# Добавление подписей значений
for bar in bars:
width = bar.get_width()
ax.text(width + 0.5, bar.get_y() + bar.get_height()/2,
f'{width:,.0f}', ha='left', va='center', fontsize=10)
ax.set_title('Метрика по Категориям (Ранжирование)', fontweight='bold')
ax.set_xlabel('Значение Метрики')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.tight_layout()
plt.savefig('bar_chart.png', dpi=150, bbox_inches='tight')
Гистограмма (Распределение)
fig, ax = plt.subplots(figsize=(10, 6))
ax.hist(df['value'], bins=30, color=PALETTE_CATEGORICAL[0], edgecolor='white', alpha=0.8)
# Добавление линий среднего и медианы
mean_val = df['value'].mean()
median_val = df['value'].median()
ax.axvline(mean_val, color='red', linestyle='--', linewidth=1.5, label=f'Среднее: {mean_val:,.1f}')
ax.axvline(median_val, color='green', linestyle='--', linewidth=1.5, label=f'Медиана: {median_val:,.1f}')
ax.set_title('Распределение Значений', fontweight='bold')
ax.set_xlabel('Значение')
ax.set_ylabel('Частота')
ax.legend()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.tight_layout()
plt.savefig('histogram.png', dpi=150, bbox_inches='tight')
Тепловая Карта
fig, ax = plt.subplots(figsize=(10, 8))
# Преобразование данных для формата тепловой карты
pivot = df.pivot_table(index='row_dim', columns='col_dim', values='metric', aggfunc='sum')
sns.heatmap(pivot, annot=True, fmt=',.0f', cmap='YlOrRd',
linewidths=0.5, ax=ax, cbar_kws={'label': 'Значение Метрики'})
ax.set_title('Метрика по Измерению Строк и Столбцов', fontweight='bold')
ax.set_xlabel('Измерение Столбцов')
ax.set_ylabel('Измерение Строк')
plt.tight_layout()
plt.savefig('heatmap.png', dpi=150, bbox_inches='tight')
Малые Множества
categories = df['category'].unique()
n_cats = len(categories)
n_cols = min(3, n_cats)
n_rows = (n_cats + n_cols - 1) // n_cols
fig, axes = plt.subplots(n_rows, n_cols, figsize=(5*n_cols, 4*n_rows), sharex=True, sharey=True)
axes = axes.flatten() if n_cats > 1 else [axes]
for i, cat in enumerate(categories):
ax = axes[i]
subset = df[df['category'] == cat]
ax.plot(subset['date'], subset['value'], color=PALETTE_CATEGORICAL[i % len(PALETTE_CATEGORICAL)])
ax.set_title(cat, fontsize=12)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# Скрыть пустые подграфики
for j in range(i+1, len(axes)):
axes[j].set_visible(False)
fig.suptitle('Тренды по Категориям', fontsize=14, fontweight='bold', y=1.02)
plt.tight_layout()
plt.savefig('small_multiples.png', dpi=150, bbox_inches='tight')
Хелперы для Форматирования Чисел
def format_number(val, format_type='number'):
"""Форматирование чисел для подписей на графиках."""
if format_type == 'currency':
if abs(val) >= 1e9:
return f'${val/1e9:.1f}B'
elif abs(val) >= 1e6:
return f'${val/1e6:.1f}M'
elif abs(val) >= 1e3:
return f'${val/1e3:.1f}K'
else:
return f'${val:,.0f}'
elif format_type == 'percent':
return f'{val:.1f}%'
elif format_type == 'number':
if abs(val) >= 1e9:
return f'{val/1e9:.1f}B'
elif abs(val) >= 1e6:
return f'{val/1e6:.1f}M'
elif abs(val) >= 1e3:
return f'{val/1e3:.1f}K'
else:
return f'{val:,.0f}'
return str(val)
# Использование с форматтером оси
ax.yaxis.set_major_formatter(mticker.FuncFormatter(lambda x, p: format_number(x, 'currency')))
Интерактивные Диаграммы с Plotly
import plotly.express as px
import plotly.graph_objects as go
# Простой интерактивный линейный график
fig = px.line(df, x='date', y='value', color='category',
title='Интерактивный Тренд Метрики',
labels={'value': 'Значение Метрики', 'date': 'Дата'})
fig.update_layout(hovermode='x unified')
fig.write_html('interactive_chart.html')
fig.show()
# Интерактивный точечный график с данными при наведении
fig = px.scatter(df, x='metric_a', y='metric_b', color='category',
size='size_metric', hover_data=['name', 'detail_field'],
title='Анализ Корреляции')
fig.show()
Принципы Дизайна
Цвет
- Используйте цвет целенаправленно: Цвет должен кодировать данные, а не служить украшением
- Выделяйте основное: Используйте яркий акцентный цвет для ключевого инсайта; остальное — серым
- Последовательные данные: Используйте градиент одного оттенка (от светлого к тёмному) для упорядоченных значений
- Дивергентные данные: Используйте градиент из двух оттенков с нейтральной серединой для данных с важным центром
- Категориальные данные: Используйте разные оттенки, максимум 6-8, чтобы не запутать
- Избегайте только красного/зелёного: 8% мужчин имеют дальтонизм по красно-зелённому спектру. Используйте синий/оранжевый как основную пару
Типография
- Заголовок отражает инсайт: «Выручка выросла на 23% г/г» лучше, чем «Выручка по месяцам»
- Подзаголовок добавляет контекст: Диапазон дат, применённые фильтры, источник данных
- Подписи осей читаемы: Никогда не поворачивайте на 90 градусов, если можно избежать. Сокращайте или переносите текст
- Подписи данных добавляют точность: Используйте на ключевых точках, а не на каждом столбце
- Аннотации выделяют: Выделяйте конкретные точки текстовыми комментариями
Компоновка
- Уменьшайте визуальный шум: Убирайте сетки, рамки, фоны, которые не несут информации
- Сортируйте осмысленно: Категории сортируйте по значению (не по алфавиту), если нет естественного порядка (месяцы, этапы)
- Подходящее соотношение сторон: Временные ряды шире, чем выше (3:1 до 2:1); сравнения могут быть более квадратными
- Белое пространство — это хорошо: Не сжимайте графики друг к другу. Дайте каждой визуализации пространство для восприятия
Точность
- Столбчатые диаграммы начинаются с нуля: Всегда. Столбец с 95 до 100 преувеличивает разницу в 5%
- Линейные графики могут иметь ненулевую базу: Когда диапазон изменений важен
- Единые шкалы на нескольких панелях: При сравнении нескольких графиков используйте одинаковый диапазон осей
- Показывайте неопределённость: Ошибочные бары, доверительные интервалы или диапазоны, если данные не точны
- Подписывайте оси: Никогда не заставляйте читателя гадать, что означают числа
Аспекты Доступности
Дальтонизм
- Никогда не полагайтесь только на цвет для различения серий данных
- Добавляйте узоры, разные стили линий (сплошные, пунктирные, точечные) или прямые подписи
- Тестируйте с помощью симуляторов дальтонизма (например, Coblis, Sim Daltonism)
- Используйте палитру, удобную для дальтоников:
sns.color_palette("colorblind")
Экранные Читалки
- Включайте альтернативный текст с описанием ключевого вывода диаграммы
- Предоставляйте таблицу данных в дополнение к визуализации
- Используйте семантические заголовки и подписи
Общая Доступность
- Достаточный контраст между элементами данных и фоном
- Минимальный размер текста: 10pt для подписей, 12pt для заголовков
- Избегайте передачи информации только через пространственное расположение (добавляйте подписи)
- Учитывайте печать: работает ли диаграмма в чёрно-белом варианте?
Чеклист Доступности
Перед публикацией визуализации:
- [ ] Диаграмма работает без цвета (узоры, подписи или стили линий различают серии)
- [ ] Текст читается при стандартном уровне масштабирования
- [ ] Заголовок описывает инсайт, а не только данные
- [ ] Оси подписаны с указанием единиц измерения
- [ ] Легенда ясна и расположена так, чтобы не закрывать данные
- [ ] Указан источник данных и диапазон дат