Несколько графиков на рисунке
До сих пор мы рисовали один график через функции plt.plot, plt.title. Для отчётов и панелей мониторинга часто нужно несколько графиков на одном рисунке. Для этого пора познакомиться с устройством matplotlib.
Figure и Axes
- Figure — весь рисунок, «лист бумаги».
- Axes — одна область с графиком на этом листе: свои оси, заголовок, линии.
На одном Figure может быть несколько Axes. Функции plt.plot, plt.title работают с «текущей» областью — для одного графика это удобно. Когда графиков несколько, лучше работать с областями явно.
plt.subplots
import matplotlib.pyplot as plt
fig, ax = plt.subplots() # рисунок с одной областью
ax.plot([1, 2, 3], [4, 1, 5])
ax.set_title("Один график")
ax.set_xlabel("x")
У области методы с приставкой set_: set_title, set_xlabel, set_ylabel, set_xlim, set_ylim. А рисуют так же: ax.plot, ax.bar, ax.hist, ax.scatter.
Сетка графиков
fig, axes = plt.subplots(2, 2) # 2 строки × 2 столбца
axes[0, 0].plot([1, 2, 3])
axes[0, 1].bar(["a", "b"], [3, 5])
axes[1, 0].hist([1, 2, 2, 3, 3, 3])
axes[1, 1].scatter([1, 2, 3], [3, 1, 2])
axes — массив numpy с областями: axes[строка, столбец].
Если строка или столбец один, массив одномерный:
fig, (left, right) = plt.subplots(1, 2) # рядом
fig, axes = plt.subplots(3, 1) # друг под другом: axes[0], axes[1], axes[2]
А при subplots(1, 1) вместо массива возвращается сама область. Чтобы код одинаково работал для любого количества графиков, используют squeeze=False — тогда axes всегда двумерный: axes[i][0].
Перебрать все области удобно так: for ax in axes.flat: ...
Размер и общий заголовок
fig, axes = plt.subplots(1, 3, figsize=(12, 4)) # ширина 12, высота 4 дюйма
fig.suptitle("Продажи по кварталам") # заголовок над всеми графиками
Если подписи наезжают друг на друга, помогает fig.tight_layout() — автоматически раздвигает графики.
Общие оси
Чтобы графики было легко сравнивать, им задают одинаковый масштаб:
fig, axes = plt.subplots(2, 1, sharex=True) # общая горизонтальная ось
Сохранение
fig.savefig("report.png", dpi=150)
Размер картинки в пикселях = figsize × dpi: при figsize=(12, 4) и dpi=150 получится 1800 × 600.
Итог
- Figure — весь рисунок, Axes — одна область с графиком;
fig, ax = plt.subplots()— одна область,plt.subplots(r, c)— сетка,axes[i, j];- у области
ax.plot,ax.bar,ax.set_title,ax.set_xlabelи т. д.; squeeze=False—axesвсегда таблица;axes.flat— перебор;figsize,fig.suptitle,tight_layout,sharex,savefig(dpi=...).