Графики 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

Синусоида, построенная функцией plot

Несколько кривых одновременно, с заголовком, легендой и подписями осей:

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)

Гистограмма 10 000 измерений, нормированная на единичную площадь

Аргумент 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(): после показа фигура очищается, и в файл записывается пустой лист.

Полезные ссылки