Как создать информативные subplots в Seaborn: полное руководство

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Для кого эта статья:

  • начинающие и опытные аналитики данных
  • специалисты по визуализации данных
  • студенты и слушатели курсов по аналитике данных

Визуализация данных превратилась из скучного отчётного этапа в мощный инструмент рассказа историй через числа. Subplots (подграфики) в Seaborn – это настоящая суперсила для аналитика, позволяющая разместить несколько графиков на одном полотне и выявить связи, которые иначе остались бы незамеченными. Однако без понимания тонкостей их создания вместо информативной визуализации можно получить запутанный набор графиков. Давайте разберёмся, как создавать subplots, которые не просто выглядят профессионально, но и эффективно доносят ваше сообщение. 📊

Хотите освоить не только создание информативных графиков в Seaborn, но и весь арсенал инструментов аналитика данных? Курс «Аналитик данных» с нуля от Skypro даёт полное погружение в мир данных – от базовых принципов Python до продвинутой визуализации и машинного обучения. После курса вы сможете не только создавать впечатляющие subplots, но и проводить комплексный анализ, который приводит к реальным бизнес-решениям.

Основы subplots в Seaborn: что нужно знать новичку

Subplots в Seaborn – это способ размещения нескольких графиков в одной фигуре. Они позволяют проводить сравнительный анализ разных наборов данных или представлять различные аспекты одного набора данных одновременно.

Начнем с основ. Seaborn работает поверх библиотеки Matplotlib, поэтому для создания подграфиков используются её инструменты. Базовый подход включает три ключевых шага:

  1. Создание Figure с помощью plt.figure()
  2. Добавление подграфиков с plt.subplot() или plt.subplots()
  3. Рисование графиков Seaborn на этих подграфиках

Рассмотрим простой пример:

Python
Скопировать код
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# Загрузка демо-данных
tips = sns.load_dataset("tips")

# Создание фигуры и подграфиков
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# Рисование на левом подграфике
sns.scatterplot(data=tips, x="total_bill", y="tip", ax=axes[0])
axes[0].set_title("Чаевые в зависимости от счета")

# Рисование на правом подграфике
sns.boxplot(data=tips, x="day", y="total_bill", ax=axes[1])
axes[1].set_title("Распределение счетов по дням недели")

plt.tight_layout()
plt.show()

Функция plt.subplots() возвращает кортеж из объекта figure и массива осей (axes). Параметры (1, 2) означают один ряд и два столбца. Аргумент ax в функциях Seaborn указывает, на каком подграфике рисовать.

Ключевые преимущества использования subplots:

  • Экономия места – вместо нескольких отдельных графиков
  • Упрощение сравнения данных
  • Представление разных аспектов данных в едином контексте
  • Создание сложных дэшбордов с минимальными усилиями
ФункцияОписаниеОсобенности
plt.subplots()Создает сетку подграфиковВозвращает figure и массив axes
plt.subplot()Создает один подграфикИспользует систему нумерации (rows, cols, index)
plt.GridSpec()Создает сложные макетыПозволяет объединять ячейки сетки
plt.tight_layout()Автоматически регулирует параметрыПомогает избежать перекрытия элементов

Алексей Морозов, Lead Data Analyst

Когда я только начинал работать с визуализацией данных, часто создавал отдельные графики и потом пытался их объединить в презентациях. Это было неэффективно и выглядело непрофессионально. Однажды мне нужно было срочно подготовить отчёт о сезонных колебаниях продаж с разбивкой по регионам. Вместо десятка разрозненных графиков я создал матрицу 3×4 с subplots, где каждый отображал динамику в конкретном регионе. Это позволило сразу увидеть, что южные регионы имели один паттерн сезонности, а северные – совершенно другой. Такое представление данных привело к пересмотру маркетинговой стратегии и увеличению продаж на 17%. Subplots превратили меня из обычного аналитика в рассказчика историй о данных.

Кинга Идем в IT: пошаговый план для смены профессии

Настройка макета и размеров Seaborn subplots

Эффективный макет subplots критически важен для ясного представления информации. Seaborn предлагает гибкие инструменты для контроля размещения и размеров подграфиков. 🔧

Рассмотрим основные способы настройки макета:

1. Базовое управление размерами и расположением

Python
Скопировать код
# Создание фигуры с определенным размером
fig, axes = plt.subplots(2, 2, figsize=(12, 8))

# Увеличение расстояния между подграфиками
fig, axes = plt.subplots(2, 2, figsize=(12, 8), gridspec_kw={'wspace': 0.3, 'hspace': 0.4})

# wspace – ширина промежутков по горизонтали (в % от ширины подграфиков)
# hspace – высота промежутков по вертикали (в % от высоты подграфиков)

2. Использование GridSpec для сложных макетов

GridSpec даёт максимальную гибкость, позволяя создавать подграфики разного размера в одной сетке:

Python
Скопировать код
import matplotlib.gridspec as gridspec

fig = plt.figure(figsize=(12, 8))
gs = gridspec.GridSpec(3, 3)

# Создаем подграфики разного размера
ax1 = fig.add_subplot(gs[0, :]) # верхняя строка полностью
ax2 = fig.add_subplot(gs[1, 0:2]) # средняя строка, первые два столбца
ax3 = fig.add_subplot(gs[1:, 2]) # две нижние строки, третий столбец
ax4 = fig.add_subplot(gs[2, 0]) # нижняя строка, первый столбец
ax5 = fig.add_subplot(gs[2, 1]) # нижняя строка, второй столбец

# Создание графиков Seaborn на этих подграфиках
sns.lineplot(data=df, x="date", y="value", ax=ax1)
sns.scatterplot(data=df, x="x", y="y", hue="category", ax=ax2)
# и т.д.

3. Автоматическая настройка макета

Python
Скопировать код
# Автоматическое выравнивание подграфиков
plt.tight_layout()

# Тонкая настройка автовыравнивания
plt.tight_layout(pad=1.5, w_pad=0.5, h_pad=1.0)
# pad – общий отступ (в дюймах)
# w_pad, h_pad – горизонтальный и вертикальный отступы между подграфиками

При выборе оптимального макета учитывайте следующие факторы:

Соотношение сторонЛучшее применениеТипичный размер (figsize)
КвадратныеКорреляционные матрицы, тепловые карты(8, 8)
ГоризонтальныеВременные ряды, сравнение категорий(12, 6)
ВертикальныеРаспределения, ранжирование(8, 12)
Широкие (16:9)Презентации, слайды(16, 9)

При работе с подграфиками разного типа следует учитывать их различные требования к пространству. Например, boxplots обычно требуют больше вертикального пространства, а barplots — больше горизонтального.

Вот практическая формула для определения размера фигуры:

Python
Скопировать код
# Начальный размер для одного подграфика
base_height = 4 # дюймы
base_width = 5 # дюймы

# Расчет размера в зависимости от количества подграфиков
rows, cols = 2, 3
figsize = (base_width * cols, base_height * rows)

fig, axes = plt.subplots(rows, cols, figsize=figsize)

Стилизация и персонализация подграфиков Seaborn

Эстетически привлекательные и профессионально оформленные подграфики привлекают внимание и улучшают восприятие данных. Seaborn предлагает богатые возможности для стилизации, позволяя создавать как единые по стилю, так и индивидуально оформленные подграфики. ✨

Начнем с установки общего стиля для всех графиков:

Python
Скопировать код
# Установка глобального стиля для всех графиков
sns.set_theme(style="whitegrid", palette="viridis")

# Доступные стили: "darkgrid", "whitegrid", "dark", "white", "ticks"

Для более тонкой настройки, можно применять стили к каждому подграфику отдельно:

Python
Скопировать код
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

with sns.axes_style("whitegrid"):
sns.barplot(data=df, x="category", y="values", ax=ax1)
ax1.set_title("Распределение по категориям", fontsize=14)

with sns.axes_style("darkgrid"):
sns.lineplot(data=df, x="date", y="trend", ax=ax2)
ax2.set_title("Тенденция во времени", fontsize=14)

Управление цветовыми схемами

Цветовые палитры – мощный инструмент для визуального разделения данных:

Python
Скопировать код
# Использование различных цветовых палитр для разных графиков
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 6))

# Категориальная палитра
sns.barplot(data=df, x="category", y="value", palette="Set2", ax=ax1)

# Последовательная палитра
sns.heatmap(correlation_matrix, cmap="YlGnBu", ax=ax2)

# Дивергентная палитра
sns.scatterplot(data=df, x="x", y="y", hue="z", palette="RdBu_r", ax=ax3)

Согласование элементов между подграфиками

Для профессионального вида важно согласовать элементы оформления между подграфиками:

Python
Скопировать код
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes = axes.flatten() # преобразуем 2D массив в 1D для удобства

# Общие настройки для всех подграфиков
for ax in axes:
ax.spines['top'].set_visible(False) # убираем верхнюю рамку
ax.spines['right'].set_visible(False) # убираем правую рамку
ax.tick_params(labelsize=10) # размер подписей осей
ax.set_xlabel('Общая метка X', fontsize=12)
ax.yaxis.grid(True, linestyle='--', alpha=0.7) # сетка только по оси Y

# Теперь рисуем разные графики
sns.lineplot(data=df1, x="x", y="y", ax=axes[0])
sns.barplot(data=df2, x="category", y="value", ax=axes[1])
# и т.д.

Создание общих легенд и подписей

Вместо отдельных легенд для каждого подграфика, часто лучше использовать одну общую:

Python
Скопировать код
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# Создаем графики без легенд
sns.scatterplot(data=df, x="x", y="y", hue="category", ax=ax1, legend=False)
sns.lineplot(data=df, x="date", y="value", hue="category", ax=ax2, legend=False)

# Создаем общую легенду
handles, labels = ax2.get_legend_handles_labels()
fig.legend(handles, labels, loc='lower center', ncol=3, bbox_to_anchor=(0.5, -0.05))

# Общий заголовок для всей фигуры
fig.suptitle('Анализ ключевых метрик', fontsize=16)

plt.tight_layout()
plt.subplots_adjust(bottom=0.15) # освобождаем место для легенды внизу

Дмитрий Соколов, Data Visualization Specialist

Мне поручили визуализировать результаты маркетинговой кампании для руководства. Данные были комплексные: конверсия по разным каналам, затраты, ROI, демографические сегменты. Я создал дашборд с восемью подграфиками, но на первой презентации столкнулся с проблемой — руководители не могли быстро понять смысл визуализаций. Они буквально "терялись" между графиками.

Я полностью переработал дашборд, применив последовательную цветовую схему: зелёные оттенки для позитивных тенденций, красные для проблемных зон. Добавил микрозаголовки прямо на графики, унифицировал форматы всех числовых меток и создал визуальную иерархию — ключевые графики сделал крупнее. Самое главное — добавил тонкие направляющие стрелки между связанными графиками.

На следующей презентации руководство не только сразу увидело основные инсайты, но и смогло самостоятельно проследить причинно-следственные связи между показателями. Бюджет на наиболее эффективный канал был увеличен на следующий квартал, что привело к росту конверсии на 23%. Я понял, что в визуализации с subplots — путеводитель для зрителя так же важен, как и сами данные.

Продвинутые техники создания subplots в Seaborn

Для создания по-настоящему информативных и впечатляющих визуализаций стоит освоить продвинутые техники работы с subplots. Эти методы позволяют решать сложные аналитические задачи и создавать визуализации публикационного качества. 🚀

1. Объединение осей с FacetGrid

FacetGrid — мощный инструмент Seaborn для создания matrix of subplots с общими осями:

Python
Скопировать код
# Создание сетки подграфиков с разбивкой по двум категориальным признакам
g = sns.FacetGrid(tips, col="time", row="sex", height=4, aspect=1.2)

# Применение одинакового графика ко всем подграфикам
g.map(sns.scatterplot, "total_bill", "tip")

# Настройка всей сетки
g.set_axis_labels("Сумма счета", "Чаевые")
g.set_titles(col_template="{col_name}", row_template="{row_name}")
g.fig.suptitle("Распределение чаевых по времени и полу", y=1.05)
g.add_legend()

2. Комбинирование разных типов графиков на одном подграфике

Python
Скопировать код
fig, ax = plt.subplots(figsize=(10, 6))

# Рисуем линейный график
sns.lineplot(data=df, x="date", y="value", marker="o", ax=ax)

# Добавляем столбчатый график с другой осью Y
ax2 = ax.twinx() # создаем вторую ось Y
sns.barplot(data=df, x="date", y="count", alpha=0.3, ax=ax2)

# Настройка осей
ax.set_xlabel("Дата")
ax.set_ylabel("Значение метрики")
ax2.set_ylabel("Количество наблюдений")

# Добавляем легенду
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax.legend(lines + lines2, labels + labels2, loc="upper left")

3. Интерактивные подграфики с синхронизацией осей

При работе с несколькими временными рядами часто требуется синхронизация осей X для удобства сравнения:

Python
Скопировать код
from matplotlib.widgets import Slider

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8), sharex=True)

# Рисуем два временных ряда
line1, = ax1.plot(dates, values1)
line2, = ax2.plot(dates, values2)

# Добавляем интерактивный слайдер для масштабирования
ax_slider = plt.axes([0\.2, 0.01, 0.65, 0.03])
slider = Slider(ax_slider, 'Zoom', 0.1, 1.0, valinit=1.0)

def update(val):
zoom = slider.val
x_min = dates[0]
x_max = dates[-1]
x_width = x_max – x_min
x_center = x_min + x_width / 2

new_width = x_width * zoom
new_min = x_center – new_width / 2
new_max = x_center + new_width / 2

ax1.set_xlim(new_min, new_max)
fig.canvas.draw_idle()

slider.on_changed(update)

4. Создание специализированных подграфиков с JointGrid

JointGrid позволяет объединять основной график с маргинальными распределениями:

Python
Скопировать код
g = sns.JointGrid(data=df, x="x", y="y", height=8)
g.plot_joint(sns.scatterplot)
g.plot_marginals(sns.kdeplot)

# Добавляем регрессионную линию
g.plot_joint(sns.regplot, scatter=False)

5. Создание сложных композиций с GridSpec

GridSpec позволяет создавать макеты с подграфиками разной величины:

Python
Скопировать код
fig = plt.figure(figsize=(12, 10))
gs = gridspec.GridSpec(3, 3)

# Главный график (занимает первые две строки и два столбца)
ax_main = fig.add_subplot(gs[0:2, 0:2])
sns.heatmap(correlation_matrix, cmap="coolwarm", annot=True, ax=ax_main)

# График распределения по строкам
ax_right = fig.add_subplot(gs[0:2, 2])
sns.boxplot(data=df, y="value", orient="v", ax=ax_right)

# Графики распределения по столбцам
ax_bottom = fig.add_subplot(gs[2, 0:2])
sns.histplot(data=df, x="other_value", kde=True, ax=ax_bottom)

# Дополнительный график
ax_corner = fig.add_subplot(gs[2, 2])
sns.scatterplot(data=df.sample(100), x="x", y="y", ax=ax_corner)

plt.tight_layout()

Такие комплексные визуализации особенно полезны для аналитических отчетов и публикаций, позволяя максимально информативно использовать пространство фигуры.

Ключевые моменты при создании продвинутых subplots:

  • Используйте sharex и sharey для создания связанных осей
  • Комбинируйте разные типы графиков для усиления информативности
  • Экспериментируйте с расположением и размерами для выделения важных элементов
  • Не перегружайте визуализацию — каждый подграфик должен иметь четкую цель
  • Для сложных макетов создавайте прототип на бумаге, прежде чем писать код

Хотите определить, какая сфера в аналитике данных подходит именно вам? Тест на профориентацию от Skypro поможет выявить ваши сильные стороны и определить лучшее направление для развития. Возможно, создание сложных визуализаций данных – именно то, в чем вы можете преуспеть благодаря вашему аналитическому мышлению и творческому подходу. Результаты теста дадут персональные рекомендации, которые помогут сосредоточиться на наиболее перспективных для вас навыках в области анализа и визуализации данных.

Практические рекомендации по эффективным subplots

Создание эффективных подграфиков требует не только технических навыков, но и понимания принципов визуальной коммуникации. Вот ключевые рекомендации для создания действительно информативных subplots. 📈

1. Оптимизируйте соотношение данных и чернил

Следуйте принципу Эдварда Тафти о максимизации "data-ink ratio" — каждый элемент должен нести информационную нагрузку:

  • Убирайте лишние рамки и линии сетки, если они не помогают интерпретировать данные
  • Минимизируйте число подписей делений осей, оставляя только действительно необходимые
  • Избегайте декоративных элементов, не связанных с данными
Python
Скопировать код
# Оптимизация ratio данных к чернилам
fig, ax = plt.subplots()

# Рисуем основной график
sns.barplot(data=df, x="category", y="value", ax=ax)

# Оптимизация графика
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.tick_params(axis='y', left=False)
ax.yaxis.grid(True, linestyle='--', alpha=0.3)

2. Соблюдайте визуальную иерархию

Создавайте визуальную иерархию между подграфиками, чтобы направлять внимание зрителя:

  • Ключевые графики должны быть крупнее или занимать центральное положение
  • Используйте более насыщенные цвета для важных элементов
  • Располагайте графики в логической последовательности (слева направо, сверху вниз)

3. Выбирайте правильные типы графиков

Цель визуализацииРекомендуемый тип графикаВажные настройки
Сравнение категорийBarplot, CatplotСортировка по величине, ограничение числа категорий
Распределение данныхHistplot, KDE, BoxplotОптимальное число бинов, отображение выбросов
Тренды во времениLineplot, temporal heatmapПравильное форматирование дат, маркеры ключевых событий
КорреляцииScatterplot, HeatmapРегрессионные линии, аннотация коэффициентов
Многомерные данныеPairplot, Parallel coordinatesОграничение числа переменных, группировка по категориям

4. Оптимизируйте для целевой аудитории

Адаптируйте сложность и детализацию в зависимости от аудитории:

  • Для технических специалистов: можно включать больше деталей, статистических аннотаций
  • Для руководства: фокус на ключевых выводах, минимум технических деталей
  • Для публикаций: соблюдение стандартов оформления, полные подписи

5. Обеспечивайте согласованность между подграфиками

Python
Скопировать код
# Создание согласованных подграфиков
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes = axes.flatten()

# Общие настройки для всех графиков
for ax in axes:
# Единый стиль для всех подграфиков
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

# Единое форматирование осей
ax.ticklabel_format(style='plain') # без научной нотации
ax.tick_params(labelsize=10)

# Если ось значений представляет один и тот же признак, установите одинаковый диапазон
if ax != axes[3]: # предполагаем, что последний график отличается
ax.set_ylim([0, df['value'].max() * 1.1])

6. Проверяйте на различных устройствах и форматах

Протестируйте, как графики будут выглядеть в различных сценариях использования:

  • Экспорт в различные форматы (PNG, PDF, SVG)
  • Тестирование на экранах разного размера
  • Проверка читаемости при печати (особенно в черно-белом варианте)
Python
Скопировать код
# Сохранение графика в различных форматах и разрешениях
plt.savefig('visualization.png', dpi=300, bbox_inches='tight')
plt.savefig('visualization.pdf', bbox_inches='tight')
plt.savefig('visualization_print.png', dpi=300, bbox_inches='tight', facecolor='white', edgecolor='none')

7. Помните про доступность

Создавайте визуализации, доступные для всех пользователей:

  • Используйте цветовые схемы, различимые людьми с нарушениями цветовосприятия (например, viridis, plasma)
  • Не полагайтесь исключительно на цвет для передачи информации
  • Обеспечивайте достаточный контраст между элементами
  • Используйте разные маркеры в дополнение к цветам на линейных графиках
Python
Скопировать код
# Создание дружественного к дальтонизму графика
sns.set_palette("viridis") # цветовая схема, различимая при дальтонизме

plt.figure(figsize=(10, 6))
sns.lineplot(
data=df, 
x="date", 
y="value", 
hue="category", 
style="category", # разные стили линий дополнительно к цветам
markers=True # маркеры для лучшей различимости
)

Создание эффективных subplots в Seaborn — искусство баланса между техническим мастерством и принципами визуальной коммуникации. Помните, что лучшая визуализация — та, которая доносит сообщение без лишних объяснений. Как сказал Ганс Рослинг: "Позвольте данным петь". Освоив техники организации подграфиков, вы превращаете сложные наборы данных в понятные визуальные истории, которые запоминаются и влияют на принятие решений.