Как в Scilab 5.5.2 сгладить график?
А как конкретно нужно сгладить? Интерполяция (гладкий график проходит через все точки) или регрессия под конкретную гладкую функцию (параболу, экспоненту итд)?
11 июн 2015 в 8:02
Первый вариант «Интерполяция (гладкий график проходит через все точки)».
11 июн 2015 в 8:07
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
В Scilab есть подходящая функция interp1, аналогичная функции matlab:
x=[1 9 15 23 30 35]; y=[4 66 19 43 24 33]; xp=linspace(0,35,100); [yp]=interp1(x, y, xp, 'spline');
Отслеживать
ответ дан 11 июн 2015 в 8:17
Dmitry Grigoryev Dmitry Grigoryev
135 7 7 бронзовых знаков
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Аппроксимация в Matlab

Приветствую! Сегодня продолжаем говорить об обработке экспериментальных данных. Сегодняшняя статья — продолжение предыдущей темы: Интерполяция в Matlab. Настоятельно советую с ней ознакомиться перед чтением данной статьи. По сути аппроксимация в Matlab очень похожа на интерполяцию, однако, для её реализации используются другие правила и функции.
Аппроксимация

Относительно интерполяции, аппроксимация получила более широкое распространение. Сущность этого метода состоит в том, что табличные данные аппроксимируют кривой, которая не обязательно должна пройти через все узловые точки, а должна как бы сгладить все случайные помехи табличной функции.
МНК (Метод Наименьших Квадратов)
Одним из самых популярных методов аппроксимации в Matlab и в других средах, это Метод Наименьших Квадратов ( МНК ). В этом методе при сглаживании опытных данных аппроксимирующую кривую стремятся провести так, чтобы её отклонения от табличных данных по всем узловым точкам были минимальными. Суть МНК заключается в следующем: для табличных данных, полученных в результате эксперимента, отыскать аналитическую зависимость, сумма квадратов уклонений которой от табличных данных во всех узловых точках была бы минимальной. Аппроксимация в Matlab по МНК осуществляется с помощью функции polyfit. Функция p = polyfit(x, y, n) находит коэффициенты полинома p(x) степени n, который аппроксимирует функцию y(x) в смысле метода наименьших квадратов. Выходом является строка p длины n+1, содержащая коэффициенты аппроксимирующего полинома.
Примеры задач
Разберём задачу, в которой разрешается использование встроенных матлабовских функций. Осуществить аппроксимацию в Matlab табличных данных x = [0, 0.1 , 0.2, 0.3, 0.5] и y = [3, 4.5, 1.7, 0.7, -1] . Применяя метод наименьших квадратов, приблизить ее многочленами 1-ой и 2-ой степени. Для каждого определить величину среднеквадратической ошибки. Построить (на одном листе) графики и заданной таблично функции (ломанная линия) и приближающих ее многочленов 1-ой и 2-ой степени.
x = [0, 0.1 , 0.2, 0.3, 0.5]; y = [3, 4.5, 1.7, 0.7, -1]; grid on plot(x, y, '*r'); xi = min(x):0.1:max(x); N = 1; % степень coeff1 = polyfit(x, y, N); y2 = 0; for k=0:N y2 = y2 + coeff1(N-k+1) * xi.^k; end hold on; plot(xi, y2, 'r'); N = 2; coeff2 = polyfit(x, y, N); y3 = 0; for k=0:N y3 = y3 + coeff2(N-k+1) * xi.^k; end hold on; plot(xi, y3, 'g'); std(y-(coeff1(1)*x+coeff1(2))) std(y-(coeff2(1)*x.^2+coeff2(2)*x+coeff2(3)))

Вывод:
ans = 0.9253
ans = 0.8973 Однако, встречаются задачи, где требуется реализовать аппроксимацию в Matlab без использования специальных функций.
Найти у(0.25) путём построения аппроксимирующего полинома методом наименьших квадратов согласно данным:
x: 0, 0.1, 0.2, 0.3, 0.5
y: 3, 4.5, 1.7, 0.7, -1
p: 0.5, 0.8, 1.6, 0.8, 0.1
Построить этот полином без учёта весовых коэффициентов с использованием определителя Вандермонда и стандартных операторов.
%Задаем массивы данных: x = [0; 0.1; 0.2; 0.3; 0.5]; y = [3;4.5;1.7;0.7;-1]; %Строим матрицу W – матрицу Вандермонда с вырезанным первым столбцом: W = vander(x); W = W(1:5,2:5); %Вычисляем элементы матрицы А как произведение транспонированной матрицы W и просто матрицы W A = W'*W; %Вычисляем элементы вектора b b = W'*y; %Решая систему уравнений Aa = b, находим значения вектор-столбца a: a = inv(A)*b %Это будут коэффициенты аппроксимирующего полинома. %Проверяем, используя методы MATLAB = функцию polyfit: qq = polyfit(x,y,3) %Получаем аппроксимированные значения y: x1 = [-0.2:0.001:0.7]; y1 = a(1)*x1.^3 + a(2)*x1.^2 + a(3)*x1 + a(4); %Строим график функции plot(x,y,'*'); hold on; grid on; plot(x1,y1,'Color','r'); %Находим значение в точке x = 0.25 x2 = 0.25; y2 = a(1)*x2^3 + a(2)*x2^2 + a(3)*x2 + a(4)

Вывод:
a =
228.1447
-176.0984
22.7745
3.1590
qq = 228.1447 -176.0984 22.7745 3.1590
y2 = 1.4113 Как видите встроенные функции для аппроксимации в Matlab укорачивают алгоритм почти вдвое. Существует также возможность реализации всего алгоритма через одну функцию, но для преподавателей студентов она скорее всего будет не приемлема. С помощью функции lsqcurvefit(fun,x0,xdata,ydata), где:
xdata,ydata– табличные значения аппроксимируемой функции;
x0 –стартовое значение параметров функции;
fun – функция аппроксимации, задаваемая пользователем С аналитически-теоретической стороны, существуют такие виды аппроксимации:
- Аппроксимация ортогональными классическими полиномами.
- Аппроксимация каноническим полиномом
Но на практике их реализацию требуют редко.
Вот и вся основная информация по аппроксимации в Matlab, если остались вопросы, задавайте их в комментариях.
Поделиться ссылкой:
Алгоритм скользящего среднего (Simple Moving Average)

Возникла задача реализовать на С++ алгоритм скользящего среднего, который находит широкое применение в обработке сигналов и статистике.
За основу была взята функция smooth в MATLAB.
Данную функцию можно использовать для фильтрации сигналов. В качестве входных параметров определяются массив данных и окно усреднения.
Кому интересно, прошу под кат
Итак, есть несколько реализаций данного алгоритма. Рассмотрим самый простой из них:
предположим, размер окна усреднения будет равен 5, тогда на каждом шаге усреднения берется текущее значение, к нему прибавляются 4 предыдущих и результат делится на 5. Очевидная проблема здесь в инициализации алгоритма, сначала нужно накопить определенное количество данных, не меньшее, чем окно усреднения.

В MATLAB алгоритм фильтрации с помощью скользящего среднего реализован в функции smooth
Пример использования smooth(input,window),
где input — массив входящих данных
window — окно усреднения.
Изменяя параметр window можно получить большую или меньшую степень сглаживания данных:
Исходник, реализующий данный пример представлен ниже:
clear all; %% Параметры t=1;% длительность сигнала Fd=512;% Частота дискретизации (Гц) A1=1;% Амплитуда синусоиды F1=10;% Частота синусоиды (Гц) SNR=0.3;% Соотношение сигнал/шум T=0:1/Fd:t;% Массив отсчетов Noise=A1*SNR*randn(1,length(T));%Сгенерированный шум Signal=A1*sind((F1*360).*T);%Сгенерированный сигнал SN=Signal+Noise; figure(1); subplot(4,1,1); plot(SN); subplot(4,1,2); plot(smooth(SN,3)); subplot(4,1,3); plot(smooth(SN,8)); subplot(4,1,4); plot(smooth(SN,20));

Для компенсации задержки в обработке сигнала, MATLAB использует динамически изменяемый размер окна, суть метода иллюстрирует следующий пример:
Собственную реализацию данного алгоритма я сначала написал в MATLAB, а затем перенес на С++
MATLAB edition:
%my_smooth %в случае, если размер окна четный, увеличиваем его на 1 для симметрии; window = 5; if(mod(window,2)==0) window=window+1; end hw=(window-1)/2; %размах окна влево и вправо от текущей позиции n=length(Signal); result=zeros(n,1); result(1)=SN(1); %первый элемент берем из исходного массива SN как есть for i=2:n %организовываем цикл по числу элементов init_sum = 0; if(i<=hw) %если индекс меньше половины окна, мы находимся в начале массива, %нужно брать окно меньшего размера k1=1; %в качестве начала окна берем первый элемент k2=2*i-1; %конец окна z=k2; %текущий размер окна elseif (i+hw>n) %если индекс+половина окна больше n - мы приближаемся к концу массива и размер окна %также нужно уменьшать k1=i-n+i; %начало окна k2=n; %конец окна - последний элемент массива z=k2-k1; %размер окна else %если первые два условия не выполняются, мы в середине массива k1=i-hw; k2=i+hw; z=window; end for j=k1:k2 %организуем цикл от начала до конца окна init_sum=init_sum+SN(j); %складываем все элементы end result(i)=init_sum/(z); %и делим на текущий размер окна end
Результат работы данной программы абсолютно совпадает с матлабовским smooth при нечетных размерах окна и несколько отличается при четном его значении (четные окна матлаб считает чуть иначе)
Исходный m-файл можно взять тут
void smooth(double *input, double *output, int n, int window) < int i,j,z,k1,k2,hw; double tmp; if(fmod(window,2)==0) window++; hw=(window-1)/2; output[0]=input[0]; for (i=1;ielse if((i+hw)>(n-1)) < k1=i-n+i+1; k2=n-1; z=k2-k1+1; >else < k1=i-hw; k2=i+hw; z=window; >for (j=k1;j <=k2;j++)< tmp=tmp+input[j]; >output[i]=tmp/z; >

спасибо за внимание, конструктивная критика приветствуется
p.s.:
Алгоритм можно оптимизировать по скорости работы изменив подсчет суммы:
Видно, что для подсчета суммы элементов на 4-м шаге нужно из суммы на третьем шаге вычесть 1-й элемент массива (2, отмечен красным) и прибавить 6-й элемент (8, желтая клетка).
На следующем шаге процедура повторяется.
Данный подход будет эффективным при большом размере окна усреднения
Язык Python
Библиотека 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 — уникальный идентификатор объекта типа. Если задан новый идентификатор, то создается новый объект и он становится активным. В случае, если передан идентификатор уже существующего объекта, то этот объект возвращается и становится активным
- /media//media/figsize : (float, float) — размер изображения в дюймах
- dpi : float — разрешение в количестве точек на дюйм
Описание других параметров функции pyplot.figure можно найти в документации. Используем эту функцию и функцию pyplot.axis чтобы улучшить наш пример с построением степенных функций:

Мы добавили две строки по сравнению с прошлой версией:
fig = plt.figure(/media//media/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, /media//media/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=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, /media//media/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
- Введение
- Настройка рабочей среды
- Язык C++
- Язык Python
- Основы синтаксиса языка python
- Строки
- Стандартные модули python, часть I
- ООП в python
- Стандартные модули II
- Итераторы и генераторы
- Вычисления с библиотекой numpy
- Визуализация данных с matplotlib