Команда Python for Devs подготовила перевод статьи о шести библиотеках Python для визуализации данных. Matplotlib, seaborn, Plotly, Altair, Pygal и Bokeh — у каждой свои сильные и слабые стороны: от академических статичных графиков до интерактивных дашбордов для бизнеса. Выбираем самую подходящую для различных кейсов.
Содержимое
Мотивация
Если вы только начинаете работать с визуализацией в Python, огромное количество библиотек и примеров может показаться пугающим. Среди популярных библиотек для визуализации — Matplotlib, seaborn, Plotly, Bokeh, Altair и Pygal.
При работе с DataFrame выбор правильной библиотеки может быть непростым: каждая из них лучше проявляет себя в определённых сценариях.
В этой статье рассмотрим плюсы и минусы каждой библиотеки. К концу вы лучше разберётесь в их возможностях и сможете осознанно выбрать наиболее подходящую.
Код: полный исходный код и Jupyter-ноутбук для этого туториала доступны на GitHub. Клонируйте репозиторий и повторяйте шаги вместе с материалом!
Главное
Вот что вы узнаете:
Разберётесь в сильных и слабых сторонах 6 ключевых библиотек для визуализации в Python
Сможете выбирать подходящую библиотеку в зависимости от требований и сложности проекта
Научитесь строить интерактивные дашборды с помощью Plotly и Bokeh для задач бизнес-аналитики
Используете статистические графики seaborn для анализа взаимосвязей в данных с минимальным количеством кода
Освоите лёгкие SVG-визуализации с Pygal для адаптивных веб-приложений
Краткая шпаргалка
Перед тем как перейти к примерам, вот подробное сравнение, которое поможет выбрать подходящую библиотеку визуализации для вашего проекта:
Возможность |
Matplotlib |
seaborn |
Pygal |
Plotly |
Altair |
Bokeh |
---|---|---|---|---|---|---|
Сложность кода |
Высокая |
Низкая |
Низкая |
Средняя |
Средняя |
Средне-высокая |
Интерактивность |
Нет (статично) |
Нет (статично) |
Базовый hover |
Продвинутая |
Основана на грамматике |
Продвинутая |
Типы графиков |
Очень много (50+) |
Основные графики |
Базовые (14 типов) |
Очень много (50+) |
Упор на статистику |
Очень много |
Интеграция с вебом |
Слабая |
Слабая |
Хорошая (SVG) |
Отличная |
Хорошая |
Отличная |
Кастомизация |
Высокая |
Ограниченная |
Средняя |
Высокая |
Средняя |
Высокая |
Зависимости |
Средние |
Средние |
Минимальные |
Большие |
Средние |
Средние |
Гид по быстрому выбору
Выбирайте Matplotlib, если: нужны статичные графики высокого качества для публикаций, требуется полный контроль над кастомизацией, работаете над академическими статьями или исследованиями.
Выбирайте seaborn, если: важно быстро строить статистические визуализации, нужны красивые графики с минимумом кода, работаете с DataFrame из pandas.
Выбирайте Pygal, если: создаёте лёгкие веб-приложения, нужны векторные графики SVG с идеальным масштабированием, важны минимальные зависимости и быстрая загрузка.
Выбирайте Plotly, если: нужны интерактивные графики с подсказками при наведении, масштабированием и кликабельными легендами; если строите веб-дашборды или приложения, где пользователю важно взаимодействовать с данными.
Выбирайте Altair, если: занимаетесь исследованием данных со статистическим уклоном, хотите использовать подход grammar-of-graphics, нужны связанные/координированные визуализации, работаете в основном в Jupyter Notebook.
Выбирайте Bokeh, если: создаёте сложные интерактивные веб-приложения, нужны связанные графики и продвинутые взаимодействия, требуется тонкая настройка веб-развёртывания или создание собственных инструментов визуализации.
Matplotlib
Matplotlib — пожалуй, самая распространённая библиотека Python для визуализации данных. Почти каждый, кто хоть раз занимался data science, наверняка использовал её хотя бы один раз.
Плюсы
Лёгкая интерпретация свойств данных
При анализе часто бывает полезно быстро взглянуть на распределение значений.
Например, если нужно посмотреть на распределение топ-100 пользователей с наибольшим количеством подписчиков, Matplotlib вполне подойдёт.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
new_profile = pd.read_csv(
"https://gist.githubusercontent.com/khuyentran1401/98658198f0ef0cb12abb34b4f2361fd8/raw/ece16eb32e1b41f5f20c894fb72a4c198e86a5ea/github\_users.csv"
)
top_followers = new_profile.sort_values(by="followers", axis=0, ascending=False)[:100]
fig = plt.figure()
plt.bar(top_followers.user_name, top_followers.followers)
plt.show()

Несмотря на не самую удачную подпись по оси X, график даёт чёткое понимание распределения данных.
Универсальность
Matplotlib очень гибкая и позволяет строить широкий спектр графиков. На сайте Matplotlib доступна подробная документация и галерея с множеством примеров, поэтому легко найти руководство почти для любого типа графика.
fig = plt.figure()
plt.text(
0.6,
0.7,
"learning",
size=40,
rotation=20.0,
ha="center",
va="center",
bbox=dict(
boxstyle="round",
ec=(1.0, 0.5, 0.5),
fc=(1.0, 0.8, 0.8),
),
)
plt.text(
0.55,
0.6,
"machine",
size=40,
rotation=-25.0,
ha="right",
va="top",
bbox=dict(
boxstyle="square",
ec=(1.0, 0.5, 0.5),
fc=(1.0, 0.8, 0.8),
),
)
plt.show()

Анимация
Matplotlib также предоставляет мощные возможности для анимации через модуль matplotlib.animation
, что позволяет создавать динамические визуализации, меняющиеся во времени. Ниже приведены три примера, демонстрирующие возможности анимации:
Анимированный линейный график с обновлением данных в реальном времени
import matplotlib.animation as animation
import numpy as np
from IPython.display import Image
fig, ax = plt.subplots()
x = np.arange(0, 2 * np.pi, 0.01)
(line,) = ax.plot(x, np.sin(x))
ax.set_ylim(-1.5, 1.5)
ax.set_title("Animated Sine Wave")
def animate(frame):
line.set_ydata(np.sin(x + frame / 10.0))
return (line,)
ani = animation.FuncAnimation(fig, animate, frames=10, interval=50, blit=True)
ani.save("sine_wave_animation.gif", writer="pillow", fps=10)
Image("sine_wave_animation.gif")

Этот пример показывает, как с помощью Matplotlib можно создавать динамические графики: синусоида плавно смещается по мере обновления кадров. Такой подход полезен для визуализации временных рядов и моделирования изменений данных во времени.
Анимированная гонка столбчатых диаграмм
# Создаём тестовые данные для анимации
categories = ["Product A", "Product B", "Product C", "Product D"]
fig, ax = plt.subplots()
def animate_bars(frame):
ax.clear()
# Симулируем изменение данных во времени
values = [np.sin(frame / 10 + i) * 50 + 60 for i in range(4)]
colors = plt.cm.viridis(np.linspace(0, 1, 4))
bars = ax.bar(categories, values, color=colors)
ax.set_ylim(0, 120)
ax.set_title(f"Sales Performance - Month {frame + 1}")
# Добавляем подписи значений на столбцы
for bar, value in zip(bars, values):
height = bar.get_height()
ax.text(
bar.get_x() + bar.get_width() / 2.0,
height + 2,
f"{value:.0f}",
ha="center",
va="bottom",
)
return bars
ani = animation.FuncAnimation(fig, animate_bars, frames=50, interval=100)
ani.save("bar_race_animation.gif", writer="pillow", fps=5)
Image("bar_race_animation.gif")

Эти примеры показывают универсальность Matplotlib: с её помощью можно создавать эффектные динамические визуализации — от научных графиков с временными рядами до бизнес-дашбордов.
Графики для публикаций
Matplotlib отлично подходит для создания высококачественных визуализаций, готовых к публикации — будь то академические статьи, исследовательские отчёты или профессиональные презентации. Библиотека позволяет тонко управлять размером фигуры, разрешением (DPI) и форматами вывода (PNG, PDF, SVG, EPS), что гарантирует соответствие строгим требованиям научных журналов и изданий.
# Настройки для графиков уровня публикаций
plt.rcParams.update({
'font.size': 10, # Стандартный размер шрифта для академических статей
'font.family': 'serif', # Традиционный шрифт с засечками для публикаций
'axes.linewidth': 1.2, # Более толстые оси для лучшей читаемости при печати
'figure.dpi': 300, # Высокое разрешение для чёткой визуализации
'savefig.dpi': 300, # Высокое разрешение для сохранённых файлов
'savefig.bbox': 'tight' # Убираем лишние поля при сохранении
})
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.suptitle('GitHub User Analysis: Publication Ready', fontsize=14, fontweight='bold')
# Подграфик 1: Гистограмма распределения
top_users = new_profile.sort_values('followers', ascending=False)[:50]
ax1.hist(top_users['followers'], bins=15, alpha=0.7, color='steelblue', edgecolor='black')
ax1.set_xlabel('Followers Count')
ax1.set_ylabel('Frequency')
ax1.set_title('A) Follower Distribution')
ax1.grid(True, alpha=0.3)
# Подграфик 2: Точечный график корреляции
ax2.scatter(top_users['followers'], top_users['total_stars'], alpha=0.6, s=30)
ax2.set_xlabel('Followers')
ax2.set_ylabel('Total Stars')
ax2.set_title('B) Followers vs Stars Correlation')
ax2.grid(True, alpha=0.3)
# Сохраняем в форматах, готовых для публикации
plt.tight_layout()
plt.savefig('github_analysis.pdf', format='pdf', bbox_inches='tight')
plt.savefig('github_analysis.eps', format='eps', bbox_inches='tight')
plt.show()
Такой подход позволяет создавать графики, которые не только наглядно показывают данные, но и соответствуют профессиональным стандартам для печати и научных публикаций.

Минусы
Крутая кривая обучения
Обширные возможности Matplotlib оборачиваются высокой сложностью. Новички часто считают её синтаксис перегруженным, особенно если привыкли к инструментам визуализации «нажми и смотри». Чтобы разобраться в иерархии figure–axes
, а также в различиях между объектно-ориентированным и pyplot
-интерфейсом, нужно вложить немало времени.
Большие усилия для доведения стандартных графиков до уровня публикации
Хотя Matplotlib поддерживает практически любой тип диаграмм, создание визуально «отшлифованных» версий привычных графиков — гистограмм, scatter plot или bar chart — требует значительной ручной настройки.
Чтобы сделать такие визуализации подходящими для презентаций или публикации, приходится вручную задавать форматирование осей, цветовые схемы, легенды, подписи и отступы. Низкоуровневый интерфейс Matplotlib обеспечивает полный контроль, но предполагает, что все аспекты оформления пользователь настроит сам.
Например, по умолчанию тепловая карта не содержит подписей осей и аннотаций внутри ячеек:
num_features = new_profile.select_dtypes("int64")
correlation = num_features.corr()
fig, ax = plt.subplots()
im = plt.imshow(correlation, cmap="coolwarm")

Чтобы сделать heatmap читаемой, нужно выполнить несколько ручных шагов:
определить компоновку и цветовую схему,
вручную разместить метки и подписи осей,
пройтись по каждой ячейке в цикле и добавить числовые значения с нужным форматированием.
Простейшая аннотированная тепловая карта в Matplotlib требует слишком много строк кода и ручных настроек:
num_features = new_profile.select_dtypes("int64")
correlation = num_features.corr()
fig, ax = plt.subplots()
im = plt.imshow(correlation, cmap="coolwarm")
ax.set_xticks(np.arange(len(correlation.columns)))
ax.set_yticks(np.arange(len(correlation.columns)))
ax.set_xticklabels(correlation.columns)
ax.set_yticklabels(correlation.columns)
# Добавляем числовые аннотации вручную
for i in range(len(correlation.columns)):
for j in range(len(correlation.columns)):
# Выбираем цвет текста в зависимости от фона
ax.text(
j,
i,
f"{correlation.iloc[i, j]:.2f}",
ha="center",
va="center",
color="black",
)
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")
plt.tight_layout()
plt.show()

Ручная статистическая обработка
В отличие от более высокоуровневых библиотек вроде seaborn, Matplotlib не выполняет статистические вычисления или предобработку данных автоматически. Все группировки, фильтрации, агрегации и расчёты приходится делать вручную.
Например, для регрессионного анализа нужно не только очистить данные, но и полностью самому посчитать коэффициенты регрессии, доверительные интервалы и ошибки:
from scipy import stats
from seaborn import load_dataset
penguins = load_dataset("penguins")
# Matplotlib требует ручной обработки статистики для регрессии
# Убираем пропуски вручную
penguins_clean = penguins.dropna(subset=["bill_length_mm", "flipper_length_mm"])
# Ручной расчёт коэффициентов регрессии
x = penguins_clean["bill_length_mm"].values
y = penguins_clean["flipper_length_mm"].values
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
# Ручной расчёт доверительных интервалов
n = len(x)
x_mean = np.mean(x)
sxx = np.sum((x - x_mean) ** 2)
y_pred = slope * x + intercept
residuals = y - y_pred
mse = np.sum(residuals**2) / (n - 2)
std_error_regression = np.sqrt(mse)
x_smooth = np.linspace(x.min(), x.max(), 100)
y_smooth = slope * x_smooth + intercept
se_y = std_error_regression * np.sqrt(1 / n + (x_smooth - x_mean) ** 2 / sxx)
t_val = stats.t.ppf(0.975, df=n - 2) # 95% доверительный интервал
ci = t_val * se_y
# Построение графика
plt.figure()
plt.scatter(x, y, alpha=0.6, s=20, color="#1f77b4", label="Data points")
plt.plot(x_smooth, y_smooth, color="#1f77b4", linewidth=2, label="Regression line")
plt.fill_between(
x_smooth,
y_smooth - ci,
y_smooth + ci,
alpha=0.2,
color="#1f77b4",
label="95% Confidence interval",
)
plt.xlabel("bill_length_mm")
plt.ylabel("flipper_length_mm")
plt.title("Penguins Regression (Manual statistical processing required)")
plt.legend()
plt.tight_layout()
plt.show()

Основные выводы
Matplotlib позволяет построить абсолютно любой график, но для создания сложных визуализаций требуется заметно больше кода по сравнению с другими библиотеками.
Seaborn
seaborn — это библиотека визуализации данных на Python, построенная поверх Matplotlib. Она предлагает более высокоуровневый интерфейс, упрощающий процесс создания привлекательных графиков.
Плюсы
Меньше кода
seaborn предоставляет удобный интерфейс, благодаря которому построение графиков проще, чем в Matplotlib. Так как библиотека ориентирована на работу с DataFrame из pandas, можно создавать наглядные визуализации с минимумом кода.
Например, используя те же данные, что и ранее, можно построить аккуратную тепловую карту без явной настройки подписей осей:
import seaborn as sns
# Загружаем датасет penguins для примеров seaborn
penguins = sns.load_dataset("penguins")
# Используем только числовые признаки для корреляции
correlation = num_features.corr()
sns.heatmap(correlation, annot=True)

В результате мы получаем более эстетичный график без дополнительной конфигурации.
Статистические графики с автоматической обработкой
seaborn прекрасно справляется с автоматическими статистическими вычислениями и агрегациями, снимая необходимость вручную подготавливать данные. Она берёт на себя оценку статистических параметров, отображение неопределённости и преобразования данных.
Автоматическая статистическая оценка с доверительными интервалами
В отличие от Matplotlib, где требуется вручную рассчитывать коэффициенты и доверительные интервалы (см. выше), seaborn позволяет построить scatter plot с трендовой линией и доверительным интервалом всего одной функцией:
# Загружаем датасет penguins и автоматически строим трендовую линию с доверительным интервалом
sns.lmplot(
data=penguins,
x="bill_length_mm",
y="flipper_length_mm",
)

Результат — аккуратная регрессионная линия с автоматически рассчитанным доверительным интервалом, без дополнительного кода.
Другие примеры статистических графиков в seaborn:
Автоматическая подгонка распределения и его визуализация:
# Автоматически строит гистограмму, KDE и rug plot
sns.displot(data=penguins, x="flipper_length_mm", kde=True, rug=True)

Автоматический расчёт корреляции и отображение маргинальных распределений:
# Автоматически строит scatter plot, маргинальные гистограммы и вычисляет коэффициент корреляции
sns.jointplot(data=penguins, x="flipper_length_mm", y="body_mass_g", kind="reg")

Автоматический анализ попарных связей:
# Автоматически создаёт scatter plot для всех числовых пар с маргинальными гистограммами
sns.pairplot(data=penguins, hue="species", palette="deep")

Визуализация распределений с использованием ядерной оценки плотности (KDE):
# Автоматически строит KDE и отображает форму распределения
sns.violinplot(data=penguins, x="species", y="body_mass_g", palette="coolwarm")

Статистическое резюме с медианой, квартилями и выбросами:
# Автоматически считает медиану, квартильные значения и выделяет выбросы
sns.boxplot(data=penguins, x="species", y="body_mass_g", palette="coolwarm")

Эти примеры наглядно показывают, как seaborn автоматически берёт на себя сложную статистическую обработку, экономя время и избавляя от необходимости писать громоздкий код.
Минусы
Ограниченные возможности кастомизации по сравнению с Matplotlib
seaborn позволяет быстро строить красивые графики, но ради простоты жертвует точной настройкой. Для сложных доработок — например, точного позиционирования элементов, нестандартных аннотаций или выделения отдельных участков — приходится обращаться к низкоуровневому интерфейсу Matplotlib, что сводит на нет преимущество простоты.
В примере ниже seaborn легко строит линейный график, но для добавления выделенного периода и кастомной аннотации приходится использовать Matplotlib:
# Загружаем датасет flights — плавный рост числа пассажиров
flights = sns.load_dataset("flights")
# seaborn строит аккуратный линейный график
sns.lineplot(data=flights, x="year", y="passengers")
# Но бизнес-аннотации требует Matplotlib
ax = plt.gca()
# Выделяем период появления реактивных самолётов
ax.axvspan(1955, 1958, alpha=0.2, color='green', label='Jet Age Introduction')
# Добавляем текстовую аннотацию
ax.annotate('Jet Engine Impact',
xy=(1957, 400),
xytext=(1952, 450),
arrowprops=dict(arrowstyle='->', color='red', lw=2),
fontsize=12, color='red', weight='bold')
# Настраиваем легенду
ax.legend(['Passenger Trend', 'Jet Age'], loc='upper left')
plt.title('Air Travel Growth with Historical Context')
plt.show()

Ограниченный набор графиков
Хотя seaborn отлично подходит для статистических визуализаций, он не охватывает такое разнообразие диаграмм, как Matplotlib, особенно в области специализированных научных или кастомных графиков.
Нет интерактивности и анимации
seaborn предназначен исключительно для статических статистических графиков и не поддерживает интерактивные элементы или анимацию.
Основные выводы
seaborn можно рассматривать как более высокоуровневую обёртку над Matplotlib. Пусть он и не обладает таким богатым набором графиков, как Matplotlib, зато позволяет строить популярные визуализации (bar plot, box plot, heatmap и др.) с минимальным количеством кода и при этом делать их эстетичными.
Pygal
Pygal — это лёгкая библиотека Python, создающая графики в формате масштабируемой векторной графики (SVG). Она разрабатывалась специально для веб-приложений и позволяет строить интерактивные визуализации с минимальными зависимостями и очень быстрой отрисовкой.
Плюсы
SVG-графика с идеальным масштабированием
Pygal генерирует чистый SVG-вывод, который масштабируется без потери качества на любых устройствах и экранах. В отличие от растровых изображений, SVG-графики остаются чёткими при любом уровне увеличения.
Это делает Pygal отличным выбором для адаптивных веб-приложений, где графики должны одинаково хорошо выглядеть и на мобильных, и на больших мониторах:
import pygal
# Строим столбчатую диаграмму топ-10 GitHub-пользователей по количеству подписчиков
top_followers = new_profile.sort_values(by="followers", ascending=False)[:10]
bar_chart = pygal.Bar(
title='Top 10 GitHub Users by Followers',
x_title='Users',
y_title='Followers'
)
bar_chart.x_labels = top_followers['user_name'].tolist()
bar_chart.add('Followers', top_followers['followers'].tolist())
# Сохраняем график в формате SVG
bar_chart.render_to_file('github_top_users.svg')

Полученный SVG можно напрямую встроить в HTML без дополнительных библиотек или файлов изображений.
Встроенная интерактивность с подсказками при наведении
Каждый график в Pygal по умолчанию поддерживает всплывающие подсказки (hover tooltips) благодаря встроенной интерактивности SVG. Пользователь может исследовать данные, наводя курсор на точки графика, и для этого не нужны никакие дополнительные JavaScript-библиотеки, фреймворки или ручная настройка.
В примере выше при наведении на столбцы автоматически показывается точное количество подписчиков, что позволяет сразу изучать данные без дополнительных усилий.
Чтобы открыть график в браузере, можно выполнить:
bar_chart.render_in_browser()

Чтобы увидеть интерактивность Pygal прямо в Jupyter Notebook, нужно подключить JavaScript-зависимости:
# Для отображения интерактивного графика в Jupyter Notebook оборачиваем SVG в HTML+JS
from IPython.display import display, HTML
def display_pygal_chart(chart):
"""Отображение графика Pygal с полной интерактивностью в Jupyter Notebook"""
html_template = """
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://kozea.github.com/pygal.js/javascripts/svg.jquery.js"></script>
<script type="text/javascript" src="https://kozea.github.io/pygal.js/2.0.x/pygal-tooltips.min.js"></script>
</head>
<body>
<figure>{chart}</figure>
</body>
</html>
"""
rendered = chart.render(is_unicode=True)
display(HTML(html_template.format(chart=rendered)))
# Отображаем график с полной интерактивностью (подсказки при наведении и др.)
display_pygal_chart(bar_chart)
Профессиональное оформление популярных типов графиков
Одно из ключевых преимуществ Pygal — автоматическое улучшение стандартных графиков: библиотека сразу делает их эстетичными и снабжает встроенной интерактивностью.
Пример: радарная диаграмма для многомерного сравнения пользователей
Сравниваем нескольких пользователей сразу по нескольким метрикам:
# Строим радарную диаграмму для многомерного сравнения
top_5_users = new_profile.sort_values(by="followers", ascending=False)[:5]
radar_chart = pygal.Radar(title="Top 5 Users: Multi-Metric Comparison", fill=True)
# Нормализуем метрики к шкале 0–100 для корректного сравнения
max_followers = top_5_users["followers"].max()
max_stars = top_5_users["total_stars"].max()
max_forks = top_5_users["forks"].max()
max_contrib = top_5_users["contribution"].max()
for _, user in top_5_users.iterrows():
radar_chart.add(
user["user_name"],
[
(user["followers"] / max_followers) * 100,
(user["total_stars"] / max_stars) * 100,
(user["forks"] / max_forks) * 100,
(user["contribution"] / max_contrib) * 100,
],
)
radar_chart.x_labels = ["Followers", "Stars", "Forks", "Contributions"]
display_pygal_chart(radar_chart)

Такой график позволяет сразу увидеть, по каким метрикам конкретный пользователь лидирует или отстаёт, и при этом сохраняет профессиональный вид «из коробки».
Box Plot – распределение возраста по классам пассажиров
Сравним распределение возраста пассажиров разных классов на «Титанике»:
# Загружаем датасет Titanic
titanic = sns.load_dataset("titanic")
# Убираем пассажиров без данных о возрасте
titanic_with_age = titanic.dropna(subset=["age"])
# Строим box plot для сравнения возраста по классам
box_plot = pygal.Box(
title="Titanic: Age Distribution by Passenger Class",
y_title="Age (years)",
box_mode="tukey", # Показывает выбросы за пределами 1.5 IQR
)
# Получаем классы пассажиров и добавляем данные для каждого
classes = ["First", "Second", "Third"]
for class_name in classes:
class_passengers = titanic_with_age[titanic_with_age["class"] == class_name]
age_data = class_passengers["age"].tolist() # Pygal принимает списки
# Добавляем класс с количеством пассажиров для контекста
passenger_count = len(class_passengers)
box_plot.add(f"{class_name} Class", age_data)
display_pygal_chart(box_plot)

Минимальные зависимости и быстрая загрузка
По сравнению с другими библиотеками, Pygal требует минимум зависимостей. Благодаря этому он идеально подходит для лёгких приложений, где важны небольшой размер при развёртывании и высокая скорость старта.
Минусы
Ограничен 14 базовыми типами графиков
Главный недостаток Pygal — ограниченный набор типов визуализаций. В арсенале только 14 базовых вариантов (bar, line, pie, scatter и т. д.), поэтому отсутствуют продвинутые статистические графики вроде violin plot, heatmap или сложные многомерные диаграммы, необходимые для серьёзного анализа данных и научной визуализации.
Основные выводы
Pygal хорош, когда нужны лёгкие и масштабируемые графики для веб-приложений. Его SVG-вывод, встроенная интерактивность и минимальные зависимости делают его отличным выбором для адаптивных дашбордов. Однако для комплексного статистического анализа или специализированных типов графиков лучше использовать другие библиотеки.
Plotly
Библиотека Plotly для Python позволяет легко строить интерактивные и высококачественные графики. Она поддерживает широкий набор типов диаграмм, схожий с Matplotlib и seaborn: линейные графики, scatter plot, area chart, bar chart и другие.
Плюсы
Простое создание красивых интерактивных графиков
Plotly особенно хорош для интерактивной визуализации, и при этом требует минимум кода. С помощью Plotly Express можно строить красивые интерактивные графики буквально одной строкой:
import plotly.express as px
fig = px.scatter(
new_profile[:100],
x="followers",
y="total_stars",
color="forks",
size="contribution",
)
fig.show()

Простота при создании сложных графиков
Plotly значительно упрощает построение графиков, которые в других библиотеках потребовали бы сложного кода.
Например, если нужно отобразить расположение GitHub-пользователей на карте по их широте и долготе, это можно сделать одной строкой:
location_df = pd.read_csv(
"https://gist.githubusercontent.com/khuyentran1401/ce61bbad3bc636bf2548d70d197a0e3f/raw/ab1b1a832c6f3e01590a16231ba25ca5a3d761f3/location\_df.csv",
index_col=0,
)
m = px.scatter_geo(
location_df,
lat="latitude",
lon="longitude",
color="total_stars",
size="forks",
hover_data=["user_name", "followers"],
title="Locations of Top Users",
)
m.show()
В этом примере цвет пузырьков показывает количество звёзд, а размер — число форков.

Возможности для бизнес-аналитики
Plotly предлагает функции уровня enterprise: интерактивные drill-down диаграммы, обновление данных в реальном времени, кросс-фильтрацию. Это позволяет бизнес-пользователям создавать полноценные дашборды, где можно исследовать взаимосвязи данных, фильтровать их по нескольким измерениям и экспортировать результаты для презентаций.
Ниже пример интерактивной круговой диаграммы с иерархическим углублением. Пользователь может кликать по уровням — от регионов до департаментов — и видеть детальную разбивку выручки:
# Создаём иерархические данные для drill-down
df = pd.DataFrame({
'Region': ['North', 'North', 'South', 'South'],
'Department': ['Sales', 'Marketing', 'Sales', 'Marketing'],
'Revenue': [250000, 180000, 200000, 150000],
'Quarter': ['Q4', 'Q4', 'Q4', 'Q4']
})
# Sunburst диаграмма для иерархического анализа
fig = px.sunburst(df, path=['Region', 'Department'],
values='Revenue',
title='Revenue Drill-down: Region → Department')
# Добавляем кросс-фильтрацию и всплывающие подсказки
fig.update_traces(textinfo="label+percent parent")
fig.update_layout(height=500)
fig.show()

Другой пример — анимированный bubble chart с временной шкалой. Пользователь может перемещаться по десятилетиям, управлять воспроизведением и изменять диапазоны через ползунки:
df = px.data.gapminder()
fig = px.scatter(
df,
x="gdpPercap",
y="lifeExp",
animation_frame="year",
size="pop",
color="continent",
log_x=True,
size_max=55,
range_x=[100, 100000],
range_y=[25, 90],
title="GDP vs Life Expectancy by Year",
)
fig.show()
Такая гибкость делает Plotly мощным инструментом как для аналитиков, так и для разработчиков интерактивных веб-дашбордов.

Минусы
Тяжёлые зависимости
Plotly поставляется с большим набором зависимостей, которые могут существенно увеличить размер проекта и усложнить развёртывание. Полный пакет включает несколько движков рендеринга, что избыточно для простых графиков и может замедлять запуск приложения.
Основные выводы
Plotly отлично подходит для создания интерактивных и качественных визуализаций при минимуме кода. Библиотека поддерживает широкий спектр графиков и упрощает работу со сложными визуализациями. Но стоит учитывать, что она тянет за собой серьёзные зависимости, увеличивающие размер и сложность проекта.
Altair
Altair — мощная декларативная библиотека статистической визуализации для Python, построенная на основе Vega-Lite. Особенно хорошо подходит для построения графиков, требующих сложных статистических преобразований.
Плюсы
Простая грамматика визуализаций
Altair использует интуитивную грамматику: достаточно указать связь между столбцами данных и визуальными каналами кодирования, остальное библиотека сделает сама. Такой подход делает процесс построения быстрым и удобным.
Например, чтобы посчитать количество людей в каждом классе на данных о «Титанике»:
import altair as alt
titanic = sns.load_dataset("titanic")
alt.Chart(titanic).mark_bar().encode(alt.X("class"), y="count()")

Краткий синтаксис Altair позволяет сосредоточиться на данных и их взаимосвязях, а не на деталях построения графиков.
Лёгкие преобразования данных
Altair упрощает выполнение преобразований прямо в коде визуализации.
Например, если нужно найти средний возраст пассажиров каждого пола в датасете Titanic, можно сделать это на лету:
hireable = (
alt.Chart(titanic)
.mark_bar()
.encode(x="sex:N", y="mean_age:Q")
.transform_aggregate(mean_age="mean(age)", groupby=["sex"])
)
hireable

Функция transform_aggregate()
позволяет агрегировать данные в процессе построения графика и сразу использовать результаты в визуализации.
Также можно явно указывать тип данных: :N
— номинальные (категориальные), :Q
— количественные.
Полный список доступных преобразований приведён здесь.
Связанные графики
Altair позволяет легко объединять несколько графиков. Например, можно использовать выделение на scatter plot для фильтрации барчарта:
brush = alt.selection_interval()
points = (
alt.Chart(titanic)
.mark_point()
.encode(
x="age:Q",
y="fare:Q",
color=alt.condition(brush, "class:N", alt.value("lightgray")),
)
.add_params(brush)
)
bars = (
alt.Chart(titanic)
.mark_bar()
.encode(y="class:N", color="class:N", x="count(class):Q")
.transform_filter(brush)
)
points & bars

При выделении диапазона на scatter plot столбчатая диаграмма динамически обновляется. Altair умеет выполнять такие интерактивные фильтрации и расчёты без необходимости поднимать Python-сервер.
Минусы
Ограниченные возможности стилизации
Простые графики (например, bar chart) по умолчанию выглядят менее выразительно, чем в seaborn или Plotly, если не задавать дополнительное оформление.
Ограничения по размеру датасета
Altair рекомендует агрегировать данные заранее, если их больше 5000 записей. Для более крупных наборов данных потребуются дополнительные шаги по оптимизации.
Основные выводы
Altair идеально подходит для статистических визуализаций благодаря интуитивной грамматике и поддержке связанных графиков, которые позволяют исследовать данные интерактивно. Он упрощает работу со сложными преобразованиями, но ограничения по стилизации и объёму данных могут потребовать обходных решений для специализированных задач.
Bokeh
Bokeh — это гибкая библиотека для построения интерактивных визуализаций, изначально ориентированная на веб-браузеры.
Плюсы
Интерактивный аналог Matplotlib
Bokeh ближе всего к Matplotlib по возможностям построения графиков, но при этом поддерживает интерактивность «из коробки». Если Matplotlib — это низкоуровневая библиотека, то Bokeh предлагает как высокоуровневый, так и низкоуровневый интерфейсы. В итоге можно строить графики, сопоставимые по сложности с Matplotlib, но с меньшим количеством кода и в более высоком разрешении.
Например, вот как выглядит круговой график в Matplotlib:
fig, ax = plt.subplots()
x = [1, 2, 3, 4, 5]
y = [2, 5, 8, 2, 7]
for x, y in zip(x, y):
ax.add_patch(
plt.Circle((x, y), 0.5, edgecolor="#f03b20", facecolor="#9ebcda", alpha=0.8)
)
# Чтобы сделать область графика квадратной
ax.set_aspect("equal", adjustable="datalim")
ax.set_xbound(3, 4)
ax.plot() # Автоматически пересчитывает масштаб
plt.show()

…а в Bokeh тот же график получается с лучшей визуализацией и интерактивностью:
from bokeh.io import show, output_notebook
from bokeh.models.glyphs import Scatter
from bokeh.plotting import figure
output_notebook()
plot = figure(tools="tap", title="Select a circle")
renderer = plot.scatter([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=50, marker="circle")
selected_circle = Scatter(size=50, fill_alpha=1, fill_color="firebrick", line_color=None, marker="circle")
nonselected_circle = Scatter(size=50, fill_alpha=0.2, fill_color="blue", line_color="firebrick", marker="circle")
renderer.selection_glyph = selected_circle
renderer.nonselection_glyph = nonselected_circle
show(plot)

В отличие от статичного вывода Matplotlib, график в Bokeh можно исследовать: выделять отдельные точки, масштабировать, панорамировать и работать с ним прямо в браузере.
Связь между графиками
Bokeh чрезвычайно упрощает установку связей между графиками. Изменения, применённые к одному графику, автоматически отражаются на другом с теми же переменными. Это позволяет исследовать взаимосвязи сразу между несколькими визуализациями.
Например, если вы строите три графика рядом и хотите наблюдать их взаимосвязь, можно использовать «linked brushing»:
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource
source = ColumnDataSource(new_profile)
TOOLS = "box_select,lasso_select,help"
TOOLTIPS = [
("user", "@user_name"),
("followers", "@followers"),
("following", "@following"),
("forks", "@forks"),
("contribution", "@contribution"),
]
s1 = figure(tooltips=TOOLTIPS, title=None, tools=TOOLS)
s1.scatter(x="followers", y="following", source=source)
s2 = figure(tooltips=TOOLTIPS, title=None, tools=TOOLS)
s2.scatter(x="followers", y="forks", source=source)
s3 = figure(tooltips=TOOLTIPS, title=None, tools=TOOLS)
s3.scatter(x="followers", y="contribution", source=source)
p = gridplot([[s1, s2, s3]])
show(p)

Благодаря использованию ColumnDataSource
одни и те же данные могут переиспользоваться несколькими графиками. Поэтому при изменениях на одном графике остальные обновляются автоматически.
Точная настройка веб-развёртывания
Bokeh даёт отличный контроль над тем, как встраивать визуализации в веб-приложения. Вы можете встраивать графики в существующие сайты, создавать автономные HTML-файлы или собирать полноценные веб-приложения с собственными серверами — всё это обеспечивает гибкую и бесшовную интеграцию.
Вот как встроить график Bokeh в существующий сайт. Сначала создайте визуализацию обычным способом:
from bokeh.plotting import figure
# Создаём тестовые данные о продажах
df = pd.DataFrame({
'sales': [100, 150, 200, 120, 180, 250, 300, 220],
'profit': [20, 30, 45, 25, 40, 60, 75, 50],
'category': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B']
})
source = ColumnDataSource(df)
# Создаем график
p = figure(title="Sales Analysis Widget", width=500, height=300)
p.scatter('sales', 'profit', source=source, size=10, alpha=0.6)
Затем сгенерируйте HTML-компоненты для встраивания:
from bokeh.embed import components
# Генерируем компоненты для встраивания
script, div = components(p)
Подключите CDN Bokeh в секции <head>
вашего HTML-шаблона:
<head>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.3.0.min.js"></script>
</head>
И добавьте компоненты графика в нужное место внутри <body>
:
<body>
<!-- Ваш существующий HTML-контент -->
{{ plot_div|safe }} <!-- Вставьте div-компонент -->
{{ plot_script|safe }} <!-- Вставьте script-компонент -->
</body>
Минусы
Многословный код
Хотя Bokeh предоставляет мощные возможности кастомизации, для создания даже простых и аккуратных графиков требуется заметно больше кода по сравнению с более высокоуровневыми библиотеками вроде seaborn или Plotly.
Например, чтобы построить простой bar chart с данными Titanic, нужно сначала агрегировать данные и дополнительно настраивать ширину столбцов и цветовую схему.
Без указания ширины график выглядит так:
from bokeh.transform import factor_cmap
from bokeh.palettes import Spectral6
titanic_groupby = titanic.groupby("class")["survived"].sum().reset_index()
p = figure(x_range=list(titanic_groupby["class"]))
p.vbar(
x="class",
top="survived",
source=titanic_groupby,
fill_color=factor_cmap(
"class", palette=Spectral6, factors=list(titanic_groupby["class"])
),
)
show(p)

Чтобы график выглядел аккуратнее, приходится вручную задавать ширину:
p = figure(x_range=list(titanic_groupby["class"]))
p.vbar(
x="class",
top="survived",
width=0.9,
source=titanic_groupby,
fill_color=factor_cmap(
"class", palette=Spectral6, factors=list(titanic_groupby["class"])
),
)
show(p)

Основные выводы
Bokeh особенно силён в веб-развёртывании: графики можно встраивать в сайты, сохранять как автономные HTML-файлы или использовать в составе полноценных веб-приложений. Но за такую гибкость приходится платить объёмным кодом — для создания визуализаций, которые в seaborn или Plotly строятся за несколько строк.
Русскоязычное сообщество про Python

Друзья! Эту статью перевела команда Python for Devs — канала, где каждый день выходят самые свежие и полезные материалы о Python и его экосистеме. Подписывайтесь, чтобы ничего не пропустить!
Заключение
Поздравляем! Вы познакомились с шестью мощными библиотеками Python для визуализации, каждая из которых лучше всего проявляет себя в разных сценариях:
Matplotlib — выбирайте, если нужен полный контроль и статичные графики высокого качества для публикаций.
seaborn — используйте для статистического анализа и элегантных графиков с минимумом кода.
Plotly — оптимален для интерактивных дашбордов и веб-визуализаций.
Altair — подойдёт для декларативного анализа данных в стиле grammar of graphics.
Pygal — лучший выбор для лёгкой интеграции с вебом и простых SVG-графиков.
Bokeh — используйте для сложных веб-приложений и гибких сценариев развёртывания.
Сопоставьте требования вашего проекта — интерактивность, уровень кастомизации или целевую платформу — и выберите библиотеку, которая даст наилучший результат.
woodiron
Полезная статья, как раз сегодня о графиках думал, помещу в закладки к вот этой 50 оттенков matplotlib — The Master Plots (с полным кодом на Python) / Хабр