Графики Matplotlib
Краткий справочник для читателей, не знакомых с Python. Полностью тема рассматривается в основных главах книги; в печатное издание приложение не вошло.
Разделы о функциях
plotиsubplotпереведены с сокращениями из учебника «Python Numpy Tutorial» курса CS231n Стэнфордского университета (автор — Дж. Джонсон; исходный текст распространяется по лицензии MIT, © 2015 Andrej Karpathy). Раздел учебника об изображениях опущен, а разделы о подписях осей, гистограммах, точках с погрешностями и сохранении в файл добавлены.
Слайды к главе. Устройство фигуры Matplotlib, основные виды графиков и сохранение в файл изложены также во второй части лекции «Визуализация данных на Python» с демонстрацией в терминале; слайды лекции доступны на сайте книги и в PDF.
Matplotlib является библиотекой для построения графиков. Ниже рассматривается минимум по модулю matplotlib.pyplot — интерфейсу, аналогичному MATLAB, в котором команды добавляются в скрытую «текущую фигуру». Явный интерфейс с объектами фигуры и осей и подробное рассмотрение визуализации на Python (Matplotlib, seaborn, Plotly, HoloViews) приведены в главе «Визуализация на Python».
import numpy as np
import matplotlib.pyplot as plt
В блокноте Jupyter графики выводятся под ячейкой. В современных версиях Jupyter это поведение включено по умолчанию, а в старых его включала команда IPython %matplotlib inline.
Построение графиков
Основной функцией matplotlib является plot, строящая графики двумерных данных:
x = np.arange(0, 3 * np.pi, 0.1) # координаты точек синусоиды
y = np.sin(x)
plt.plot(x, y) # график средствами matplotlib

Несколько кривых одновременно, с заголовком, легендой и подписями осей:
y_sin = np.sin(x)
y_cos = np.cos(x)
plt.plot(x, y_sin) # обе кривые в одних осях
plt.plot(x, y_cos)
plt.xlabel('x, рад')
plt.ylabel('f(x)')
plt.title('Синус и косинус')
plt.legend(['sin(x)', 'cos(x)'])

В физике график без подписанных осей графиком не считается. На осях всегда должны быть указаны величина и её единицы измерения («t, с», «U, мВ»); за это отвечают plt.xlabel и plt.ylabel. Заголовок задаётся функцией plt.title, а plt.legend выводит легенду со списком кривых и их названий.
Имя кривой удобнее задавать непосредственно в plot через аргумент label: в этом случае plt.legend() вызывается без аргументов, и соответствие кривых и подписей не нарушается. Координатная сетка plt.grid(True) облегчает считывание значений с графика.
plt.plot(x, y_sin, label='sin(x)')
plt.plot(x, y_cos, '--', label='cos(x)') # '--' — штриховая линия
plt.xlabel('x, рад')
plt.ylabel('f(x)')
plt.title('Тригонометрические функции')
plt.legend() # имена кривых возьмутся из label
plt.grid(True) # координатная сетка
Subplots
Функция subplot размещает несколько графиков на одном рисунке:
x = np.arange(0, 3 * np.pi, 0.1) # координаты точек синусоиды и косинусоиды
y_sin = np.sin(x)
y_cos = np.cos(x)
plt.subplot(2, 1, 1) # сетка 2 × 1, активен первый подграфик
plt.plot(x, y_sin)
plt.title('Синус')
plt.subplot(2, 1, 2) # активен второй подграфик
plt.plot(x, y_cos)
plt.title('Косинус')
plt.tight_layout() # поля без наложения подписей
plt.show() # вывод рисунка

Подробнее о функции subplot — в документации.
Гистограммы
Гистограмма строится первой, когда имеется набор повторных измерений: она показывает распределение значений. Ниже генерируются 10 000 «измерений», рассеянных вокруг истинного значения по закону Гаусса, и строится их гистограмма функцией plt.hist.
rng = np.random.default_rng(0) # генератор случайных чисел NumPy
# 10 000 «измерений»: истинное значение 5,0, случайный шум 0,5
values = rng.normal(loc=5.0, scale=0.5, size=10000)
plt.hist(values, bins=50, density=True, alpha=0.7)
plt.xlabel('Измеренное значение')
plt.ylabel('Плотность вероятности')
plt.grid(True)

Аргумент bins задаёт число корзин: при слишком малом значении распределение теряет детали, при слишком большом гистограмма становится шумной. Флаг density=True нормирует гистограмму на единичную площадь, и в этих осях её можно сравнивать с теоретической плотностью вероятности, например с гауссианой. Полупрозрачность alpha необходима, когда несколько распределений накладываются друг на друга.
Точки с погрешностями (errorbar)
Основным графиком в экспериментальной физике являются точки с погрешностями. Его строит plt.errorbar: кроме координат точек она принимает величины ошибок по осям (yerr и xerr) и рисует отрезки погрешностей.
# «Эксперимент»: период маятника в зависимости от длины подвеса
L = np.array([0.2, 0.4, 0.6, 0.8, 1.0]) # длина, м
T = 2 * np.pi * np.sqrt(L / 9.81) # теоретический период, с
T_exp = T + rng.normal(0, 0.03, T.size) # «измеренный» период, с
T_err = np.full_like(T, 0.05) # погрешность измерения, с
plt.errorbar(L, T_exp, yerr=T_err, fmt='o', capsize=3, label='эксперимент')
plt.plot(L, T, '--', label='теория')
plt.xlabel('L, м')
plt.ylabel('T, с')
plt.legend()
plt.grid(True)

Ключ fmt='o' необходим, поскольку экспериментальные точки изображаются маркерами и не соединяются ломаной; рядом проводится теоретическая кривая или аппроксимация. Аргумент capsize задаёт размер засечек на концах отрезков, а xerr добавляет горизонтальные отрезки, если погрешность имеется и по оси x.
Сохранение рисунка в файл
Графики существуют внутри блокнота. Для вставки рисунка в отчёт или статью его сохраняют в файл с помощью plt.savefig; формат определяется расширением имени файла.
plt.plot(x, np.sin(x))
plt.savefig('sine.png', dpi=300, bbox_inches='tight') # растровый формат
plt.savefig('sine.pdf') # векторный формат
PNG является растровым форматом, поэтому для печати необходимо задавать разрешение dpi=300 или выше. PDF и SVG — векторные форматы, не теряющие чёткости при любом увеличении; для статей и дипломов (особенно в LaTeX) предпочтителен pdf. Аргумент bbox_inches='tight' обрезает лишние белые поля вокруг рисунка. В скриптах savefig необходимо вызывать до plt.show(): после показа фигура очищается, и в файл записывается пустой лист.
Полезные ссылки
- в официальной документации Matplotlib удобно начать с раздела Tutorials;
- Галерея примеров — сотни готовых графиков с исходным кодом; зачастую проще найти похожий пример, чем писать с нуля;
- Официальные шпаргалки (cheatsheets) укладывают всю библиотеку на пару страниц;
- Anatomy of a figure показывает, из каких частей состоит рисунок matplotlib и как эти части называются;
- Scientific Visualization: Python + Matplotlib, бесплатная книга Николя Ружье о научной визуализации.