Как создать несколько графиков Matplotlib на одном рисунке

Вы можете использовать следующий синтаксис для создания нескольких графиков Matplotlib на одном рисунке:
import matplotlib.pyplot as plt #define grid of plots fig, axs = plt.subplots(nrows= 2 , ncols= 1 ) #add data to plots axs[0].plot(variable1, variable2) axs[1].plot(variable3, variable4)
В следующих примерах показано, как использовать эту функцию на практике.
Пример 1: сложите графики вертикально
В следующем коде показано, как создать три графика Matplotlib, расположенные вертикально:
#create some data var1 = [1, 2, 3, 4, 5, 6] var2 = [7, 13, 16, 18, 25, 19] var3 = [29, 25, 20, 25, 20, 18] #define grid of plots fig, axs = plt.subplots(nrows= 3 , ncols= 1 ) #add title fig. suptitle('Plots Stacked Vertically') #add data to plots axs[0].plot(var1, var2) axs[1].plot(var1, var3) axs[2].plot(var2, var3)

Пример 2: сложить графики по горизонтали
В следующем коде показано, как создать три графика Matplotlib, расположенные горизонтально:
#create some data var1 = [1, 2, 3, 4, 5, 6] var2 = [7, 13, 16, 18, 25, 19] var3 = [29, 25, 20, 25, 20, 18] #define grid of plots fig, axs = plt.subplots(nrows= 1 , ncols= 3 ) #add title fig. suptitle('Plots Stacked Horizontally') #add data to plots axs[0].plot(var1, var2) axs[1].plot(var1, var3) axs[2].plot(var2, var3)

Пример 3: создание сетки графиков
Следующий код показывает, как создать сетку графиков Matplotlib:
#create some data var1 = [1, 2, 3, 4, 5, 6] var2 = [7, 13, 16, 18, 25, 19] var3 = [29, 25, 20, 25, 20, 18] var4 = [4, 4, 6, 4, 7, 11] #define grid of plots fig, axs = plt.subplots(nrows= 2 , ncols= 2 ) #add title fig. suptitle('Grid of Plots') #add data to plots axs[0, 0].plot(var1, var2) axs[0, 1].plot(var1, var3) axs[1, 0].plot(var1, var4) axs[1, 1].plot(var3, var1)

Пример 4: Совместное использование осей между участками
Вы можете использовать аргументы sharex и sharey , чтобы убедиться, что несколько графиков используют одну и ту же ось X:
#create some data var1 = [1, 2, 3, 4, 5, 6] var2 = [7, 13, 16, 18, 25, 19] var3 = [29, 25, 20, 25, 20, 18] var4 = [4, 4, 6, 4, 7, 11] #define grid of plots fig, axs = plt.subplots(nrows= 2 , ncols= 2 , sharex= True , sharey= True ) #add title fig. suptitle('Grid of Plots with Same Axes') #add data to plots axs[0, 0].plot(var1, var2) axs[0, 1].plot(var1, var3) axs[1, 0].plot(var1, var4) axs[1, 1].plot(var3, var1)
Пострение графиков
Фундаментальная задача программирования — вычисление математических и, в частности, алгебраических функций. Казалось бы, что проще? Однако, запись выражения на языке математики не принимается напрямую языком программирования. Выражение нужно написать в виде, который будет понятен тому или иному языку программирования.
Например, y = x², должно быть записано как y = x*x или y = x**2 .
Упражнение №1
Запишите выражение, заданное формулой, в виде, подходящем для языка Python.

и найдите его значения в точках 1, 10, 1000.
Для вычисления математических функций мы не будем использовать стандартную библиотеку math. Т.к. она не работает с векторами. В нашем случае разумней обратить внимание на библиотеку numpy. Данная библиотека обеспечивает удобную работу с векторам.
Т.е., если у нас есть вектор x=[1, 2, 3, 4] и мы вызовим numpy.log(x), то логарифм будет взят от каждого элемента списка и возвращен будет список значений.
Аналогичная функция в модуля math ожидает число, т.е. нельзя сделать math.log(x), нужно делать math.log(x[0]) и т.д.
Традиционно библиотека numpy подключается командой:
import numpy as np
Данный вызов сообщает, что подключить numpy под псевдонимом np. Это делается, чтобы не писать каждый раз:
numpy.cos(x)
np.cos(x)
Такой код, с более коротким именем библиотеки, элементарно, проще читать.
Основные математические функции и константы функии, которые нам понадобятся из numpy:
| Функция библиотеки math | Математическая функция |
|---|---|
| np.pi | Число pi |
| np.e | Число e |
| np.cos | Косинус |
| np.sin | Синус |
| np.tan | Тангенс |
| np.acos | Арккосинус |
| np.asin | Арксинус |
| np.atan | Арктангенс |
| np.exp | Экспонента |
| np.log | Логарифм |
Функция log вычисляет натуральный логарифм. Чтобы вычислить логарифм по другому основанию, нужно воспользоваться формулой перехода. Например, если мы хотим получить логарифм x по основанию 2, нужно написать:
np.log(x) / np.log(2)
Построение графиков
matplotlib — набор дополнительных модулей (библиотек) языка Python. Предоставляет средства для построения самых разнообразных 2D графиков и диаграмм данных. Отличается простотой использования — для построения весьма сложных и красочно оформленных диаграмм достаточно нескольких строк кода. При этом качество получаемых изображений более чем достаточно для их публикования. Также позволяет сохранять результаты в различных форматах, например Postscript, и, соответственно, вставлять изображения в документы TeX. Предоставляет API для встраивания своих графических объектов в приложения пользователя.
Пример построения графика функции:
import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 10.01, 0.01) plt.plot(x, x**2) plt.show()

На одном рисунке можно построить несколько графиков функций:
import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 10.01, 0.01) plt.plot(x, np.sin(x), x, np.cos(x), x, -x) plt.show()

Также довольно просто на график добавить служебную информацию и отобразить сетку:
import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 10.01, 0.01) plt.plot(x, np.sin(x), x, np.cos(x), x, -x) plt.xlabel(r'$x$') plt.ylabel(r'$f(x)$') plt.title(r'$f_1(x)=\sin(x),\ f_2(x)=\cos(x),\ f_3(x)=-x$') plt.grid(True) plt.show()

Или используя legend() , где можно указать место расположения подписей к кривым на графике в параметре loc . Подписи могут быть явно переданы legend((line1, line2, line3), (‘label1’, ‘label2’, ‘label3’)) или могут быть переданы в аргумет label , как в примере ниже. Чтобы сохранить график нужно воспользоваться savefig(figure_name) , где figure_name явлется строкой назания файла с указанием расширения. Для текстовых полей можно изменять шрифт ( fontsize ), для большей читаемости графика, а его размер указывается с помощью figure(figsize=(10, 5)) .
import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 10.01, 0.01) plt.figure(figsize=(10, 5)) plt.plot(x, np.sin(x), label=r'$f_1(x)=\sin(x)$') plt.plot(x, np.cos(x), label=r'$f_2(x)=\cos(x)$') plt.plot(x, -x, label=r'$f_3(x)=-x$') plt.xlabel(r'$x$', fontsize=14) plt.ylabel(r'$f(x)$', fontsize=14) plt.grid(True) plt.legend(loc='best', fontsize=12) plt.savefig('figure_with_legend.png') plt.show()

Текстовые поля в matplotlib могут содержать разметку LaTeX, заключенную в знаки $. Буква r перед кавычками говорит python, что символ «\» следует оставить как есть и не интерпретировать как начало спецсимвола (например, перевода строки — «\n»).
Работа с matplotlib основана на использовании графических окон и осей (оси позволяют задать некоторую графическую область). Все построения применяются к текущим осям. Это позволяет изображать несколько графиков в одном графическом окне. По умолчанию создаётся одно графическое окно figure(1) и одна графическая область subplot(111) в этом окне. Команда subplot позволяет разбить графическое окно на несколько областей. Она имеет три параметра: nr , nc , np . Параметры nr и nc определяют количество строк и столбцов на которые разбивается графическая область, параметр np определяет номер текущей области ( np принимает значения от 1 до nr*nc ). Если nr*nc
import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 10.01, 0.01) t = np.arange(-10, 11, 1) #subplot 1 sp = plt.subplot(221) plt.plot(x, np.sin(x)) plt.title(r'$\sin(x)$') plt.grid(True) #subplot 2 sp = plt.subplot(222) plt.plot(x, np.cos(x), 'g') plt.axis('equal') plt.grid(True) plt.title(r'$\cos(x)$') #subplot 3 sp = plt.subplot(223) plt.plot(x, x**2, t, t**2, 'ro') plt.title(r'$x^2$') #subplot 4 sp = plt.subplot(224) plt.plot(x, x) sp.spines['left'].set_position('center') sp.spines['bottom'].set_position('center') plt.title(r'$x$') plt.show()

График может быть построен в полярной системе координат, для этого при создании subplot необходимо указать параметр polar=True :
import numpy as np import matplotlib.pyplot as plt plt.subplot(111, polar=True) phi = np.arange(0, 2*np.pi, 0.01) rho = 2*phi plt.plot(phi, rho, lw=2) plt.show()

Или может быть задан в параметрической форме (для этого не требуется никаких дополнительных действий, поскольку два массива, которые передаются в функцию plot воспринимаются просто как списки координат точек, из которых состоит график):
import numpy as np import matplotlib.pyplot as plt t = np.arange(0, 2*np.pi, 0.01) r = 4 plt.plot(r*np.sin(t), r*np.cos(t), lw=3) plt.axis('equal') plt.show()

График функции двух переменных может быть построен, например, так:
from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt import numpy as np ax = axes3d.Axes3D(plt.figure()) i = np.arange(-1, 1, 0.01) X, Y = np.meshgrid(i, i) Z = X**2 - Y**2 ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) plt.show()

Добавление текста на график: Команду text() можно использовать для добавления текста в произвольном месте (по умолчанию координаты задаются в координатах активных осей), а команды xlabel() , ylabel() и title() служат соответственно для подписи оси абсцисс, оси ординат и всего графика. Для более полной информации смотрите «Text introduction» раздел на оф. сайте.
import numpy as np import matplotlib.pyplot as plt mu, sigma = 100, 15 x = mu + sigma * np.random.randn(10000) # the histogram of the data n, bins, patches = plt.hist(x, 50, density=True, facecolor='g', alpha=0.75) plt.xlabel('Smarts') plt.ylabel('Probability') plt.title('Histogram of IQ') plt.text(60, .030, r'$\mu=100,\ \sigma=15$') plt.text(50, .033, r'$\varphi_<\mu,\sigma^2>(x) = \frac <\sigma\sqrt<2\pi>> \,e^< -\frac<(x- \mu)^2>> = \frac \varphi\left(\frac\right),\quad x\in\mathbb $', fontsize=20, color='red') plt.axis([40, 160, 0, 0.04]) plt.grid(True) plt.show()

plot() — универсальная команда и в неё можно передавать произвольное количество аргументов. Например, для того, чтобы отобразить y в зависимости от x , можно выполнить команду:
import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4], [1, 4, 9, 16]) plt.show()

Каждую последовательность можно отобразить своим типом точек:
import numpy as np import matplotlib.pyplot as plt # равномерно распределённые значения от 0 до 5, с шагом 0.2 t = np.arange(0., 5., 0.2) # красные чёрточки, синие квадраты и зелёные треугольники plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^') plt.show()

Также в matplotlib существует возможность строить круговые диаграммы:
import numpy as np import matplotlib.pyplot as plt data = [33, 25, 20, 12, 10] plt.figure(num=1, figsize=(6, 6)) plt.axes(aspect=1) plt.title('Plot 3', size=14) plt.pie(data, labels=('Group 1', 'Group 2', 'Group 3', 'Group 4', 'Group 5')) plt.show()

И аналогичным образом столбчатые диаграммы:
import numpy as np import matplotlib.pyplot as plt objects = ('A', 'B', 'C', 'D', 'E', 'F') y_pos = np.arange(len(objects)) performance = [10,8,6,4,2,1] plt.bar(y_pos, performance, align='center', alpha=0.5) plt.xticks(y_pos, objects) plt.ylabel('Value') plt.title('Bar title') plt.show()

Цветовые карты используются, если нужно указать в какие цвета должны окрашиваться участки трёхмерной поверхности в зависимости от значения Z в этой области. Цветовую карту можно задать самому, а можно воспользоваться готовой. Рассмотрим использование цветовой карты на примере графика функции z(x,y)=sin(x)*sin(y)/(x*y) .
import pylab from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import numpy def makeData(): x = numpy.arange(-10, 10, 0.1) y = numpy.arange(-10, 10, 0.1) xgrid, ygrid = numpy.meshgrid(x, y) zgrid = numpy.sin(xgrid)*numpy.sin(ygrid)/(xgrid*ygrid) return xgrid, ygrid, zgrid x, y, z = makeData() fig = pylab.figure() axes = Axes3D(fig) axes.plot_surface(x, y, z, rstride=4, cstride=4, cmap=cm.jet) pylab.show()

Альтернативой к использованию mpl_toolkits.mplot3d является библиотека plotly , которая позволяет интерактивно взаимодействовать с графиком, поворачивая его или увеличивая некоторую область в пространсте.
Функция eval()
В Python есть встроенная функция eval() , которая выполняет строку с кодом и возвращает результат выполнения:
>>> eval("2 + 3*len('hello')") 17 >>>
Это очень мощная, но и очень опасная инструкция, особенно если строки, которые вы передаёте в eval , получены не из доверенного источника. Если строкой, которую мы решим скормить eval() , окажется «os.system(‘rm -rf /’)» , то интерпретатор честно запустит процесс удаления всех данных с компьютера.
Упражнение №2
Постройте график функции
и по графику найдите найдите корни уравнения y(x) = 0. (Не нужно применять численных методов — просто приблизьте график к корням функции настолько, чтобы было удобно их найти.)
Упражнение №3
Постройте график функции

Упражнение №4
Используя функцию eval() постройте график функции, введённой с клавиатуры. Чтобы считать данные с клавиатуры, используйте функцию input() . Попробуйте включить эффект «рисование от руки» посредством вызова plt.xkcd() . Посольку эта функция применяет некоторый набор настроек, избавиться от которых впоследствие не так просто, удобнее использовать ее как «контекстный менеджер» — это позволяет применить настройки временно, только к определенному блоку кода. Для этого используется ключевое слово with:
with plt.xkcd(): plt.pie([70, 10, 10, 10], labels=('В комментариях', 'В Ираке', 'В Сирии', 'В Афганистане')) plt.title('Где ведутся самые ожесточенные бои')

Отображение погрешностей
С помощью метода plt.errorbar можно рисовать точки с погрешностями измерений, как для лабораторных работ. Погрешности по осям абсцисс и ординат задаются в параметрах (соответственно) xerr и yerr .
import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [0.99, 0.49, 0.35, 0.253, 0.18] plt.errorbar(x, y, xerr=0.05, yerr=0.1) plt.grid() plt.show()

Альтернативой для plt.errorbar может слудить plt.fill_between , который заполняет область графика между кривыми, чтобы регулировать прозрачность используется аргумент alpha . Это число из отрезка [0, 1], на которое домножоается интенсивность цвета заполнения между кривыми.
import numpy as np import matplotlib.pyplot as plt x = np.arange(0, 10, 0.01) plt.plot(x, x**2, label=r'$f = x^2$') plt.scatter(x, x**2 + np.random.randn(len(x))*x, s=0.3) plt.fill_between(x, 1.3*x**2, 0.7*x**2, alpha=0.3) plt.legend(loc='best') plt.savefig('figure_fill_between.png') plt.show()

В уже использованном модуле numpy есть метод polyfit, позволяющий приближать данные методом наименьших квадратов. Он возвращает погрешности и коэффициенты полученного многочлена.
x = [1, 2, 3, 4, 5, 6] y = [1, 1.42, 1.76, 2, 2.24, 2.5] p, v = np.polyfit(x, y, deg=1, cov=True) >>> p array([0.28517032, 0.80720757]) >>> v array([[0.00063242, -0.00221348], [-0.00221348, 0.00959173]])
Многочлен задается формулой p(x) = p[0] * x**deg + . + p[deg]
Для того, чтобы не выписывать каждый раз руками эту формулу для разных степеней, есть функция poly1d , которая возвращает функцию полинома, описанного точками p. Возвращенная функция может принимать на вход не только число, но и список значений, в таком случае, будет вычислено значение функции в каждой точке списка и возвращен список результатов.
p_f = np.poly1d(p) p_f(0.5) p_f([1, 2, 3])
Упражнение №5
Приблизить данные из приведённого примера с погрешностями или свои собственные (из лабораторного практикума по общей физике) многочленами первой и второй степени. Начертить точки с погрешностями и полученные аппроксимационные кривые на одном графике.
Упражнение №6 *
Постройте график функции Вейерштрасса
Сайт построен с использованием Pelican. За основу оформления взята тема от Smashing Magazine. Исходные тексты программ, приведённые на этом сайте, распространяются под лицензией GPLv3, все остальные материалы сайта распространяются под лицензией CC-BY.
Визуализация данных с matplotlib
Библиотека matplotlib содержит большой набор инструментов для двумерной графики. Она проста в использовании и позволяет получать графики высокого качества. В этом разделе мы рассмотрим наиболее распространенные типы диаграмм и различные настройки их отображения.
Модуль matplotlib.pyplot предоставляет процедурный интерфейс к (объектно-ориентированной) библиотеке matplotlib, который во многом копирует инструменты пакета MATLAB. Инструменты модуля pyplot де-факто являются стандартным способом работы с библиотекой matplotlib , поэтому мы органичимся рассмотрением этого пакета.
Двумерные графики
pyplot.plot
Нарисовать графики функций sin и cos с matplotlib.pyplot можно следующим образом:
import numpy as np import matplotlib.pyplot as plt phi = np.linspace(0, 2.*np.pi, 100) plt.plot(phi, np.sin(phi)) plt.plot(phi, np.cos(phi)) plt.show()
В результате получаем

Мы использовали функцию plot, которой передали два параметра — списки значений по горизонтальной и вертикальной осям. При последовательных вызовах функции plot графики строятся в одних осях, при этом происходит автоматическое переключение цвета.
fmt = '[marker][line][color]'
функции plot позволяет задавать тип маркера, тип линии и цвет. Приведем несколько примеров:
x = np.linspace(0, 1, 100) f1 = 0.25 - (x - 0.5)**2 f2 = x**3 plt.plot(x, f1, ':b') # пунктирная синяя линия plt.plot(x, f2, '--r') # штрихованная красная линия plt.plot(x, f1+f2, 'k') # черная непрерывная линия plt.show()

rg = np.random.Generator(np.random.PCG64()) plt.plot(rg.binomial(10, 0.3, 6), 'ob') # синие круги plt.plot(rg.poisson(7, 6), 'vr') # красные треугольники plt.plot(rg.integers(0, 10, 6), 'Dk') # черные ромбы plt.show()

Из последнего примера видно, что если в функцию plot передать только один список y , то он будет использован для значений по вертикальной оси. В качестве значений по горизонтальной оси будет использован range(len(y)) .
Более тонкую настройку параметров можно выполнить, передавая различные именованные аргументы, например:
- marker : str — тип маркера
- markersize : float — размер маркера
- linestyle : str — тип линии
- linewidth : float — толщина линии
- color : str — цвет
Полный список доступных параметров можно найти в документации.
pyplot.errorbar
Результаты измерений в физике чаще всего представлены в виде величин с ошибками. Функция plt.errorbar позволяет отображать такие данные:
rg = np.random.Generator(np.random.PCG64(5)) x = np.arange(6) y = rg.poisson(149, x.size) plt.errorbar(x, y, yerr=np.sqrt(y), marker='o', linestyle='none') plt.show()

Ошибки можно задавать и для значений по горизонтальной оси:
rg = np.random.Generator(np.random.PCG64(5)) N = 6 x = rg.poisson(169, N) y = rg.poisson(149, N) plt.errorbar(x, y, xerr=np.sqrt(x), yerr=np.sqrt(y), marker='o', linestyle='none') plt.show()

Ошибки измерений могут быть асимметричными. Для их отображения в качестве параметра yerr (или xerr ) необходимо передать кортеж из двух списков:
rg = np.random.Generator(np.random.PCG64(11)) N = 6 x = np.arange(N) y = rg.poisson(149, N) yerr = [ 0.7*np.sqrt(y), 1.2*np.sqrt(y) ] plt.errorbar(x, y, yerr=yerr, marker='o', linestyle='none') plt.show()

Функция pyplot.errorbar поддерживает настройку отображения графика с помощью параметра fmt и всех именованных параметров, которые доступны в функции pyplot . Кроме того, здесь появляются параметры для настройки отображения линий ошибок (“усов”):
- ecolor : str — цвет линий ошибок
- elinewidth : float — ширина линий ошибок
- capsize : float — длина “колпачков” на концах линий ошибок
- capthick : float — толщина “колпачков” на концах линий ошибок
и некоторые другие. Изменим параметры отрисовки данных из предыдущего примера:
# . plt.errorbar(x, y, yerr=yerr, marker='o', linestyle='none', ecolor='k', elinewidth=0.8, capsize=4, capthick=1) plt.show()

Настройки отображения
Наши графики все еще выглядят довольно наивно. В этой части мы рассмотрим различные настройки, которые позволят достичь качества оформления диаграмм, соответствующего, например, публикациям в рецензируемых журналах.
Диапазон значений осей
Задавать диапазон значений осей в matplotlib можно несколькими способами. Например, так:
pyplot.xlim([0, 200]) # диапазон горизонтальной оси от 0 до 200 pyplot.xlim([0, 1]) # диапазон вертикальной оси от 0 до 1
Размер шрифта
Размер и другие свойства шрифта, который используется в matplotlib по умолчанию, можно изменить с помощью объекта matplotlib.rcParams :
matplotlib.rcParams.update('font.size': 14>)
Объект matplotlib.rcParams хранит множество настроек, изменяя которые, можно управлять поведением по умолчанию. Смотрите подробнее в документации.
Подписи осей
Подписи к осям задаются следующим образом:
plt.xlabel('run number', fontsize=16) plt.ylabel(r'average current ($\mu A$)', fontsize=16)
В подписях к осям (и вообще в любом тексте в matplotlib) можно использовать инструменты текстовой разметки TeX, позволяющие отрисовывать различные математические выражения. TeX-выражения должны быть внутри пары символов $ , кроме того, их следует помещать в r-строки, чтобы избежать неправильной обработки.
Заголовок
Функция pyplot.title задает заголовок диаграммы. Применим наши новые знания:
import numpy as np import matplotlib.pyplot as plt import matplotlib # задаем размер шрифта matplotlib.rcParams.update('font.size': 12>) rg = np.random.Generator(np.random.PCG64(11)) x = np.arange(6) y = rg.poisson(149, x.size) yerr = [ 0.7*np.sqrt(y), 1.2*np.sqrt(y) ] plt.errorbar(x, y, yerr=yerr, marker='o', linestyle='none', ecolor='k', elinewidth=0.8, capsize=4, capthick=1) # добавляем подписи к осям и заголовок диаграммы plt.xlabel('run number', fontsize=16) plt.ylabel(r'average current ($\mu A$)', fontsize=16) plt.title(r'The $\alpha^\prime$ experiment. Season 2020-2021') # задаем диапазон значений оси y plt.ylim([0, 200]) # оптимизируем поля и расположение объектов plt.tight_layout() plt.show()

В этом примере мы использовали функцию pyplot.tight_layout, которая автоматически подбирает параметры отображения так, чтобы различные элементы не пересекались.
Легенда
При построении нескольких графиков в одних осях полезно добавлять легенду — пояснения к каждой линии. Следующий пример показывает, как это делается с помощью аргументов label и функции pyplot.legend :
import numpy as np import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams.update('font.size': 12>) x = np.linspace(0, 1, 100) f1 = 0.25 - (x - 0.5)**2 f2 = x**3 # указываем в аргументе label содержание легенды plt.plot(x, f1, ':b', label='1st component') plt.plot(x, f2, '--r', label='2nd component') plt.plot(x, f1+f2, 'k', label='total') plt.xlabel(r'$x$', fontsize=16) plt.ylabel(r'$f(x)$', fontsize=16) plt.xlim([0, 1]) plt.ylim([0, 1]) # выводим легенду plt.legend(fontsize=14) plt.tight_layout() plt.show()

Функция pyplot.legend старается расположить легенду так, чтобы она не пересекала графики. Аргумент loc позволяет задать расположение легенды вручную. В большинстве случаев расположение по умолчанию получается удачным. Детали и описание других аргументов смотрите в документации.
Сетка
Сетка во многих случаях облегчает анализ графиков. Включить отображение сетки можно с помощью функции pyplot.grid . Аргумент axis этой функции имеет три возможных значения: x , y и both и определяет оси, вдоль которых будут проведены линии сетки. Управлять свойствами линии сетки можно с помощью именованных аргументов, которые мы рассматривали выше при обсуждении функции pyplot.plot .
В matplotlib поддерживается два типа сеток: основная и дополнительная. Выбор типа сетки выполняется с помощью аргумента which , который может принимать три значения: major , minor и both . По умолчанию используется основная сетка.
Линии сетки привязаны к отметкам на осях. Чтобы работать с дополнительной сеткой необходимо сначала включить вспомогательные отметки на осях (которые по умолчанию отключены и к которым привязаны линии дополнительной сетки) с помощью функции pyplot.minorticks_on . Приведем пример:
import numpy as np import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams.update('font.size': 12>) x = np.linspace(-1, 1, 250) plt.plot(x, x, label=r'$x$') plt.plot(x, x**2, label=r'$x^2$') plt.plot(x, x**3, label=r'$x^3$') plt.plot(x, np.cbrt(x), label=r'$x^$') plt.legend(fontsize=16) # включаем дополнительные отметки на осях plt.minorticks_on() plt.xlabel(r'$x$', fontsize=16) plt.xlim([-1., 1.]) plt.ylim([-1., 1.]) # включаем основную сетку plt.grid(which='major') # включаем дополнительную сетку plt.grid(which='minor', linestyle=':') plt.tight_layout() plt.show()

Логарифмический масштаб
Функции pyplot.semilogy и pyplot.semilogx выполняют переключение между линейным и логарифмическим масштабами осей. В некоторых случаях логарифмический масштаб позволяет отобразить особенности зависимостей, которые не видны в линейном масштабе. Вот так выглядят графики экспоненциальных функций в линейном масштабе:

plt.semilogy()
делает график гораздо более информативным:

Теперь мы видим поведение функций во всем динамическом диапазоне, занимающем 12 порядков.
Произвольные отметки на осях
Вернемся к первому примеру, в котором мы строили графики синуса и косинуса. Сделаем так, чтобы на горизонтальной оси отметки соответствовали различным долям числа pi и имели соответствующие подписи:

Метки на горизонтальной оси были заданы с помощью функции pyplot.xticks :
plt.xticks( np.linspace(-np.pi, np.pi, 9), [r'$-\pi$', r'$-3\pi/4$', r'$-\pi/2$', r'$-\pi/4$', r'$0$', r'$\pi/4$', r'$+\pi/2$', r'$3\pi/4$', r'$+\pi$'])
Модуль pyplot.ticker содержит более продвинутые инструменты для управления отметками на осях. Подробности смотрите в документации.
Размер изображения
До сих пор мы строили графики в одном окне, размер которого был задан по умолчанию. За кадром matplotlib создавал объект типа Figure, который определяет размер окна и содержит все остальные элементы. Кроме того, автоматически создавался объект типа Axis. Подробнее работа с этими объектами будет рассмотрена ниже. Сейчас же мы рассмотрим функцию pyplot.figure , которая позволяет создавать новые объекты типа Figure и переключаться между уже созданными объектами.
Функция pyplot.figure может принимать множество аргументов. Вот основные:
- num : int или str — уникальный идентификатор объекта типа. Если задан новый идентификатор, то создается новый объект и он становится активным. В случае, если передан идентификатор уже существующего объекта, то этот объект возвращается и становится активным
- figsize : (float, float) — размер изображения в дюймах
- dpi : float — разрешение в количестве точек на дюйм
Описание других параметров функции pyplot.figure можно найти в документации. Используем эту функцию и функцию pyplot.axis чтобы улучшить наш пример с построением степенных функций:

Мы добавили две строки по сравнению с прошлой версией:
fig = plt.figure(figsize=(6, 6)) # . plt.axis('equal')
Функция pyplot.axis позволяет задавать некоторые свойства осей. Ее вызов с параметром ‘equal’ делает одинаковыми масштабы вертикальной и горизонтальной осей, что кажется хорошей идеей в этом примере. Функция pyplot.axis возвращает кортеж из четырех значений xmin, xmax, ymin, ymax , соответствующих границам диапазонов значений осей.
Некоторые другие способы использования функции pyplot.axis :
- Кортеж из четырех float задаст новые границы диапазонов значений осей
- Строка ‘off’ выключит отображение линий и меток осей
Гистограммы
Обратимся теперь к другим типам диаграмм. Функция pyplot.hist строит гистограмму по набору значений:
import numpy as np import matplotlib.pyplot as plt rg = np.random.Generator(np.random.PCG64(5)) data = rg.poisson(145, 10000) plt.hist(data, bins=40) # для краткости мы опускаем код для настройки осей, сетки и т.д.

Аргумент bins задает количество бинов гистограммы. По умолчанию используется значение 10. Если вместо целого числа в аргумент bins передать кортеж значений, то они будут использованы для задания границ бинов. Таким образом можно построить гистограмму с произвольным разбиением.
Некоторые другие аргументы функции pyplot.hist :
- range : (float, float) — диапазон значений, в котором строится гистограмма. Значения за пределами заданного диапазона игнорируются.
- density : bool . При значении True будет построена гистограмма, соответствующая плотности вероятности, так что площадь гистограммы будет равна единице.
- weights : список float значений того же размера, что и набор данных. Определяет вес каждого значения при построении гистограммы.
- histtype : str . может принимать значения . Определяет тип отрисовки гистограммы.
В качестве первого аргумента можно передать кортеж наборов значений. Для каждого из них будет построена гистограмма. Аргумент stacked со значением True позволяет строить сумму гистограмм для кортежа наборов. Покажем несколько примеров:

rg = np.random.Generator(np.random.PCG64(5)) data1 = rg.poisson(145, 10000) data2 = rg.poisson(140, 2000) # левая гистограмма plt.hist([data1, data2], bins=40) # центральная гистограмма plt.hist([data1, data2], bins=40, histtype='step') # правая гистограмма plt.hist([data1, data2], bins=40, stacked=True)
В физике гистограммы часто представляют в виде набора значений с ошибками, предполагая при этом, что количество событий в каждом бине является случайной величиной, подчиняющейся биномиальному распределению. В пределе больших значений флуктуации количества событий в бине могут быть описаны распределением Пуассона, так что характерная величина флуктуации определяется корнем из числа событий. Библиотека matplotlib не имеет инструмента для такого представления данных, однако его легко получить с помощью комбинации numpy.histogram и pyplot.errorbar :
def poisson_hist(data, bins=60, lims=None): """ Гистограмма в виде набора значений с ошибками """ hist, bins = np.histogram(data, bins=bins, range=lims) bins = 0.5 * (bins[1:] + bins[:-1]) return (bins, hist, np.sqrt(hist)) rg = np.random.Generator(np.random.PCG64(5)) data = rg.poisson(145, 10000) x, y, yerr = poisson_hist(data, bins=40, lims=(100, 190)) plt.errorbar(x, y, yerr=yerr, marker='o', markersize=4, linestyle='none', ecolor='k', elinewidth=0.8, capsize=3, capthick=1)

Диаграммы рассеяния
Распределение событий по двум измерениям удобно визуализировать с помощью диаграммы рассеяния:
rg = np.random.Generator(np.random.PCG64(5)) means = (0.5, 0.9) covar = [ [1., 0.6], [0.6, 1.] ] data = rg.multivariate_normal(means, covar, 5000) plt.scatter(data[:,0], data[:,1], marker='o', s=1)

Каждой паре значений в наборе данных соответствует одна точка на диаграмме. Несмотря на свою простоту, диаграмма рассеяния позволяет во многих случаях наглядно представлять двумерные данные. Функция pyplot.scatter позволяет визуализировать и данные более высокой размерности: размер и цвет маркера могут быть заданы для каждой точки отдельно:
rg = np.random.Generator(np.random.PCG64(4)) data = rg.uniform(-1, 1, (50, 2)) col = np.arctan2(data[:, 1], data[:, 0]) size = 100*np.sum(data**2, axis=1) plt.scatter(data[:,0], data[:,1], marker='o', s=size, c=col)

Цветовую палитру можно задать с помощью аргумента cmap . Подробности и описание других аргументов функции pyplot.scatter можно найти в документации.
Контурные диаграммы
Контурные диаграммы позволяют визуализировать функции двух переменных:
from scipy import stats means = (0.5, 0.9) covar = [ [1., 0.6], [0.6, 1.] ] mvn = stats.multivariate_normal(means, covar) x, y = np.meshgrid( np.linspace(-3, 3, 80), np.linspace(-2, 4, 80) ) data = np.dstack((x, y)) # левая диаграмма — без заливки цветом plt.contour(x, y, mvn.pdf(data), levels=10) # правая диаграмма — с заливкой цветом plt.contourf(x, y, mvn.pdf(data), levels=10)

Аргумент levels задает количество контуров. По умолчанию контуры отрисовываются равномерно между максимальным и минимальным значениями. В аргумент levels также можно передать список уровней, на которых следует провести контуры.
Обратите внимание на использование функций numpy.meshgrid и numpy.dstack в этом примере.
Контурную диаграмму можно дополнить цветовой полосой colorbar , вызвав функцию pyplot.colorbar :
cs = plt.contourf(x, y, mvn.pdf(data), levels=15, cmap=matplotlib.cm.magma_r) cbar = plt.colorbar(cs)

Более подробное описание функций plt.contour и plt.contourf смотрите в документации.
Расположение нескольких осей в одном окне
В одном окне (объекте Figure ) можно разместить несколько осей (объектов axis.Axis ). Функция pyplot.subplots создает объект Figure , содержащий регулярную сетку объектов axis.Axis :
import numpy as np from scipy import stats import matplotlib.pyplot as plt fig, axes = plt.subplots(ncols=3, nrows=2, figsize=(12, 8)) x = np.linspace(0.01, 25, 250) for idx, row in enumerate(axes): for jdx, ax in enumerate(row): ndf = idx * 3 + jdx + 1 y = stats.chi2.pdf(x, ndf) ax.plot(x, y, label=fr'$\chi^2_ndf>>>(x)$') ax.set_xlabel(r'$x$', fontsize=16) ax.set_ylim([0, 1.05*y.max()]) ax.minorticks_on() ax.legend(fontsize=16) ax.grid(which='major') ax.grid(which='minor', linestyle=':') fig.tight_layout() plt.show()

Количество строк и столбцов, по которым располагаются различные оси, задаются с помощью параметров nrows и ncols , соответственно. Функция pyplot.subplots возвращает объект Figure и двумерный список осей axis.Axis . Обратите внимание на то, что вместо вызовов функций модуля pyplot в этом примере использовались вызовы методов классов Figure и axis.Axis .
В последнем примере горизонтальная ось во всех графиках имеет один и тот же диапазон. Аргумент sharex функции pyplot.subplots позволяет убрать дублирование отрисовки осей в таких случаях:
fig, axes = plt.subplots(ncols=3, nrows=2, figsize=(12, 8), sharex=True) # . for idx, row in enumerate(axes): for jdx, ax in enumerate(row): # . if idx: ax.set_xlabel(r'$x$', fontsize=16)

Существует аналогичный параметр sharey для вертикальной оси.
Более гибкие возможности регулярного расположения осей предоставляет функция pyplot.subplot. Мы не будем рассматривать эту функцию и ограничимся лишь ее упоминанием.
Функция pyplot.axes позволяет добавлять новые оси в текущем окне в произвольном месте:
import numpy as np import matplotlib.pyplot as plt exno = 26 rg = np.random.Generator(np.random.PCG64(5)) x1 = rg.exponential(10, 5000) x2 = rg.normal(10, 0.1, 100) # Строим основную гистограмму plt.hist([x1, x2], bins=150, range=(0, 60), stacked=True) plt.minorticks_on() plt.xlim((0, 60)) plt.grid(which='major') plt.grid(which='minor', linestyle=':') # Строим вторую гистограмму в отдельных осях plt.axes([.5, .5, .4, .4]) plt.hist([x1, x2], bins=100, stacked=True, range=(9, 11)) plt.grid(which='major') plt.tight_layout() # сохраняем диаграмму в файл plt.savefig('histograms.png') plt.show()

В этом примере была использована функция pyplot.savefig , сохраняющая содержимое текущего окна в файл в векторном или растровом формате. Формат задается с помощью аргумента format или автоматически определяется из имени файла (как в примере выше). Набор доступных форматов зависит от окружения, однако в большинстве случаев можно использовать такие форматы как png , jpeg , pdf , svg и eps .
Резюме
Предметом изучения в этом разделе был модуль pyplot библиотеки matplotlib , содержащий инструменты для построения различных диаграмм. Были рассмотрены:
- функции для построения диаграмм pyplot.plot , pyplot.errorbar . pyplot.hist , pyplot.scatter , pyplot.contour и pyplot.contourf ;
- средства настройки свойств линий и маркеров;
- средства настройки координатных осей: подписи, размер шрифта, координатная сетка, произвольные метки др.;
- инструмены для расположения нескольких координатных осей в одном окне.
Рассмотренные инструменты далеко не исчерпывают возможности библиотеки matplotlib , однако их должно быть достаточно в большинстве случаев для визуализации данных. Мы рекомендуем заинтересованному читалелю изучить список источников, в которых можно найти много дополнительной информации.
Источники
- matplotlib.pyplot
- Pyplot tutorial
- Colormaps
- Scipy Lecture Notes
Как вывести несколько графиков одновременно?
Написал код по заданию. В результате работы программы по очереди появляются три окна с графиками. Нужно сделать так, чтобы они появлялись одновременно , а не один после закрытия другого или три полноценных графика в одном окне . Помогите пожалуйста.
import random import matplotlib.pyplot as plt import numpy as np import pandas as pd plt.style.use('ggplot') mn, mx, N = -10000, 10000, 1000 dataset = pd.Series(data=[random.randint(mn, mx) for _ in range(1000)], name='X') print("Характеристики полученных целочисленных данных :\n") print(f"Минимальное значение : ") print(f"Количество повторяющихся значений : ") print(f"Максимальное значение : ") print(f"Сумма чисел : ") plt.plot(list(range(1000)), dataset, alpha=0.8) plt.title("Линейный график\n(по заданным целочисленным данным)") plt.show() plt.hist(dataset, alpha=0.8) plt.title('Гистограмма значений \n(по заданным целочисленным данным)') plt.show() dataframe = pd.DataFrame(dataset) dataframe['X_по_возрастанию'] = dataframe.X.sort_values().values dataframe['X_по_убыванию'] = dataframe.X.sort_values(ascending=False).values dataframe.head() plt.plot(dataframe['X_по_возрастанию'], label="X по возрастанию") plt.plot(dataframe['X_по_убыванию'], label="X по убыванию") plt.title('Два линейных графика отсортированных значений\n(по заданным целочисленным данным)') plt.legend() plt.show()
Отслеживать
73.7k 112 112 золотых знаков 38 38 серебряных знаков 55 55 бронзовых знаков
задан 2 мая 2021 в 10:26
11 1 1 золотой знак 1 1 серебряный знак 4 4 бронзовых знака
удалите все вызовы plt.show() кроме последнего
2 мая 2021 в 10:30
Может что-то не так делаю, но в таком случае график едет и все в куче. Надо в идеале чтобы три окна одновременно появлялись. Или три полноценных графика в одном окне.
2 мая 2021 в 10:33
это уже следующий вопрос 😉 Для того чтобы графики не «съезжали» значения различных графиков должны лежать приблизительно в одинаковых диапазонах. В противном случае графики будут «ехать»
2 мая 2021 в 10:40
А вывод нескольких окон одновременно возможен? В моем случае 3
2 мая 2021 в 10:48
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Для того чтобы отобразить несколько независимых графиков в одном окне — предназначена функция subplot() из пакета pylab .
import random import matplotlib.pyplot as plt import numpy as np import pandas as pd # Импортируем один из пакетов Matplotlib import pylab plt.style.use('ggplot') mn, mx, N = -10000, 10000, 1000 dataset = pd.Series(data=[random.randint(mn, mx) for _ in range(1000)], name='X') print("Характеристики полученных целочисленных данных :\n") print(f"Минимальное значение : ") print(f"Количество повторяющихся значений : ") print(f"Максимальное значение : ") print(f"Сумма чисел : ") # Две строки, два столбца. Текущая ячейка - 1 pylab.subplot (2, 2, 1) pylab.plot(list(range(1000)), dataset, alpha=0.8) pylab.title ("Линейный график") # Две строки, два столбца. Текущая ячейка - 3 pylab.subplot (2, 2, 3) pylab.hist(dataset, alpha=0.8) #plot (xlist, ylist) pylab.title ("Гистограмма значений") dataframe = pd.DataFrame(dataset) dataframe['X_по_возрастанию'] = dataframe.X.sort_values().values dataframe['X_по_убыванию'] = dataframe.X.sort_values(ascending=False).values dataframe.head() # Две строки, два столбца. Текущая ячейка - 2 pylab.subplot (1, 2, 2) pylab.plot (dataframe['X_по_возрастанию'], label="X по возрастанию") pylab.plot (dataframe['X_по_убыванию'], label="X по убыванию") pylab.title ("Два линейных графика") # Покажем окно с нарисованным графиком pylab.show()

Отслеживать
ответ дан 2 мая 2021 в 11:38
73.7k 112 112 золотых знаков 38 38 серебряных знаков 55 55 бронзовых знаков
Ответ @S.Nick в целом верен, но у него есть один большой недостаток: в нём используется matplotlib.pylab . Разработчики matplotlib рекомендуют пользоваться pyplot .
pylab был разработан для упрощения жизни тем людям, кто переходит в Python из MATLAB. Этот пакет импортирует в глобальное пространство имён все рисовальные функции pyplot И вычислительные функции numpy , благодаря чему пайтоновский скрипт становится похожим на матлабовский. Типа такого:
from pylab import * x = linspace(-3, 3, 30) y = x**2 plot(x, y) show()
Вызовы pylab.subplot работают, но несколько бессмысленны, так как это прямые синонимы функций из pyplot . В ответе S.Nick вы можете заменить все обращения к pylab.subplot на вызов оригинала pyplot.subplot :
import random import matplotlib.pyplot as plt import numpy as np import pandas as pd plt.style.use('ggplot') mn, mx, N = -10000, 10000, 1000 dataset = pd.Series(data=[random.randint(mn, mx) for _ in range(1000)], name='X') print("Характеристики полученных целочисленных данных :\n") print(f"Минимальное значение : ") print(f"Количество повторяющихся значений : ") print(f"Максимальное значение : ") print(f"Сумма чисел : ") # Две строки, два столбца. Текущая ячейка - 1 plt.subplot (2, 2, 1) plt.plot(list(range(1000)), dataset, alpha=0.8) plt.title ("Линейный график") # Две строки, два столбца. Текущая ячейка - 3 plt.subplot (2, 2, 3) plt.hist(dataset, alpha=0.8) #plot (xlist, ylist) plt.title ("Гистограмма значений") dataframe = pd.DataFrame(dataset) dataframe['X_по_возрастанию'] = dataframe.X.sort_values().values dataframe['X_по_убыванию'] = dataframe.X.sort_values(ascending=False).values dataframe.head() # Две строки, два столбца. Текущая ячейка - 2 plt.subplot (1, 2, 2) plt.plot (dataframe['X_по_возрастанию'], label="X по возрастанию") plt.plot (dataframe['X_по_убыванию'], label="X по убыванию") plt.title ("Два линейных графика") plt.show()