📉 Matplotlib
Полный справочник: Figure и Axes, типы графиков, оформление, подписи, оси, цвета, subplots и GridSpec, аннотации, стили, 3D, анимации, сохранение и рецепты для данных.
Шпаргалки · ИИ · #matplotlib #python #visualization #plots #data-science
Идея и установка
Matplotlib строит графики в Python. Иерархия: Figure (холст) → Axes (область графика с осями) → артисты (линии, текст, подписи). Два стиля: быстрый plt.plot(...) (pyplot, неявное состояние) и объектно-ориентированный (fig, ax = plt.subplots()): используйте его, он предсказуем.
pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline # в Jupyter; %matplotlib widget — интерактивно
Первый график
x = np.linspace(0, 10, 200)
fig, ax = plt.subplots(figsize=(8, 4), dpi=120, layout="constrained") # constrained — автоматическая раскладка
ax.plot(x, np.sin(x), label="sin", color="tab:blue", linestyle="--", linewidth=2, marker="o", markevery=20)
ax.plot(x, np.cos(x), label="cos", color="#e11d48")
ax.set(title="Синус и косинус", xlabel="x", ylabel="y", xlim=(0, 10), ylim=(-1.2, 1.2))
ax.grid(True, alpha=.3)
ax.legend(loc="upper right", frameon=False)
fig.savefig("plot.png", dpi=200, bbox_inches="tight", transparent=False)
plt.show()
Типы графиков
| Тип | Код |
|---|---|
| Линия | ax.plot(x, y), ax.step(x, y), ax.stairs |
| Точки | ax.scatter(x, y, c=z, s=sizes, cmap="viridis", alpha=.7) |
| Столбцы | ax.bar(labels, values, yerr=err), ax.barh(...); группы: сдвиг по x + width |
| Гистограмма | ax.hist(data, bins=30, density=True, alpha=.6), ax.hist2d |
| Круговая | ax.pie(vals, labels=labs, autopct="%1.0f%%", startangle=90) |
| «Ящик с усами» | ax.boxplot([a, b], labels=["A", "B"]), ax.violinplot |
| Тепловая карта | im = ax.imshow(M, cmap="coolwarm"); fig.colorbar(im, ax=ax), ax.pcolormesh |
| Область | ax.fill_between(x, y1, y2, alpha=.3), ax.stackplot(x, ys) |
| Ошибки | ax.errorbar(x, y, yerr=e, fmt="o-", capsize=3) |
| Контуры, векторы | ax.contourf(X, Y, Z), ax.quiver, ax.streamplot |
| Другое | ax.hexbin, ax.stem, ax.polar, ax.table, ax.axhline / axvline / axhspan / axvspan |
# сгруппированные столбцы
w = .38; i = np.arange(len(cats))
ax.bar(i - w/2, a, w, label="A"); ax.bar(i + w/2, b, w, label="B"); ax.set_xticks(i, cats)
Несколько графиков
fig, axes = plt.subplots(2, 2, figsize=(10, 6), sharex=True, sharey="row", layout="constrained")
axes[0, 0].plot(x, y); axes[0, 1].hist(data); axes[1, 0].scatter(x, y); axes[1, 1].imshow(M)
for ax in axes.flat: ax.grid(alpha=.3)
fig.suptitle("Общий заголовок")
fig = plt.figure(figsize=(9, 5))
gs = fig.add_gridspec(2, 3) # произвольные ячейки
ax1 = fig.add_subplot(gs[0, :]); ax2 = fig.add_subplot(gs[1, :2]); ax3 = fig.add_subplot(gs[1, 2])
fig, axd = plt.subplot_mosaic([["main", "side"], ["main", "bottom"]]) # по именам
ax_twin = ax.twinx() # вторая ось Y
inset = ax.inset_axes([.6, .6, .35, .35]) # врезка
Оформление и подписи
ax.set_title("Заголовок", fontsize=14, loc="left"); ax.set_xlabel("x", fontsize=12); ax.set_ylabel("y")
ax.set_xticks([0, 5, 10], labels=["a", "b", "c"]); ax.tick_params(axis="x", rotation=45, labelsize=9)
ax.set_xscale("log"); ax.set_yscale("symlog"); ax.invert_yaxis(); ax.set_aspect("equal")
ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda v, _: f"{v:,.0f}".replace(",", " ")))
from matplotlib.ticker import MaxNLocator, PercentFormatter; ax.yaxis.set_major_formatter(PercentFormatter(1.0))
ax.spines[["top", "right"]].set_visible(False)
ax.text(2, .5, "текст", fontsize=10, ha="center", va="bottom", bbox=dict(boxstyle="round", fc="w", ec="gray"))
ax.annotate("пик", xy=(1.57, 1), xytext=(3, .6), arrowprops=dict(arrowstyle="->", color="k"))
ax.bar_label(bars, fmt="%.1f", padding=2) # значения над столбцами
ax.legend(title="Серии", ncol=2, bbox_to_anchor=(1.02, 1), loc="upper left") # легенда снаружи
Русский язык и шрифты: plt.rcParams["font.family"] = "DejaVu Sans" (поддерживает кириллицу), либо шрифт системы. Знак минуса: plt.rcParams["axes.unicode_minus"] = False.
Цвета и карты
Именованные ("tab:blue", "crimson"), hex, RGB-кортежи, серый "0.5". Цикл цветов: plt.rcParams["axes.prop_cycle"]. Карты: последовательные (viridis, plasma, Blues), расходящиеся (coolwarm, RdBu) для данных вокруг нуля, качественные (tab10, Set2) для категорий. Избегайте jet. Для людей с нарушением цветового зрения подходят viridis, cividis.
cmap = plt.get_cmap("viridis"); colors = cmap(np.linspace(0, 1, 5))
from matplotlib.colors import Normalize, LogNorm, TwoSlopeNorm
im = ax.imshow(M, norm=TwoSlopeNorm(vcenter=0))
Стили и настройки
plt.style.use("seaborn-v0_8-whitegrid") # print(plt.style.available): ggplot, bmh, dark_background, fivethirtyeight
with plt.style.context("dark_background"): ...
plt.rcParams.update({"font.size": 12, "axes.titlesize": 14, "figure.dpi": 120, "axes.spines.top": False, "axes.spines.right": False})
Свой стиль: файл .mplstyle и plt.style.use("my.mplstyle").
Работа с данными
df.plot(x="date", y=["a", "b"], kind="line", ax=ax) # pandas строит через Matplotlib
ax.plot(df["date"], df["value"]); fig.autofmt_xdate() # даты на оси
import matplotlib.dates as mdates; ax.xaxis.set_major_formatter(mdates.DateFormatter("%d.%m")); ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.fill_between(df.index, df.lo, df.hi, alpha=.2) # доверительный интервал
ax.scatter(x, y, c=group.map(color_map)) # цвет по категории
Для статистических графиков удобнее Seaborn (sns.histplot, sns.boxplot, sns.heatmap, sns.pairplot, sns.lmplot) поверх Matplotlib.
3D и анимация
ax = fig.add_subplot(projection="3d"); ax.plot_surface(X, Y, Z, cmap="viridis"); ax.scatter(x, y, z); ax.view_init(30, 45)
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(); line, = ax.plot([], [])
def update(frame): line.set_data(x[:frame], y[:frame]); return line,
ani = FuncAnimation(fig, update, frames=len(x), interval=30, blit=True)
ani.save("anim.gif", writer="pillow", fps=30) # mp4: writer="ffmpeg"
Сохранение
fig.savefig("a.png", dpi=200, bbox_inches="tight"), форматы png, jpg, svg, pdf, eps. Для публикаций векторные (svg, pdf), для веба png/webp. Размер в дюймах: ширина колонки журнала ~3.5 дюйма. plt.close(fig) освобождает память в циклах.
Интерактивность
Окна plt.show(), виджеты (matplotlib.widgets.Slider, Button), события (fig.canvas.mpl_connect("button_press_event", f)). Для интерактива в вебе: Plotly, Bokeh, Altair, Dash.
Хорошие практики визуализации
- Подписывайте оси и единицы измерения, заголовок говорит вывод.
- Начинайте столбцы с нуля; не используйте 3D и круговые диаграммы без нужды.
- Минимум линий и цветов, сортируйте категории, подписывайте напрямую вместо легенды, где можно.
- Подбирайте тип графика под вопрос: сравнение (столбцы), динамика (линия), распределение (гистограмма, ящик), связь (scatter), состав (stacked bar).
- Одинаковые шкалы при сравнении панелей (
sharey=True).
Частые ошибки
- Смешение стилей
plt.plotи объектного: путаница с текущими осями. - Накопление графиков в цикле без
plt.close. - Наложение подписей:
layout="constrained", поворот меток,fig.tight_layout(). - Кириллица квадратиками: нет подходящего шрифта.
plt.show()блокирует в скриптах; в серверной среде используйте бэкендAgg(matplotlib.use("Agg")).- Огромные данные: прореживание,
hexbin,datashader,rasterized=True.