Начнем изучение
пакета matplotlib с наиболее
часто используемой функции plot(). На предыдущем занятии мы с ее
помощью построили простой двумерный график:
import matplotlib.pyplot as plt
plt.plot([1, 2, -6, 0, 4])
plt.show()
Также обратите
внимание, что мы обращаемся к ветке matplotlib.pyplot для вызова этой
функции. В целом, именно модуль pyplot отвечает за отображение разных
графиков – это «рабочая лошадка» пакета matplotlib.
Давайте первым
делом разберемся, что на вход принимает эта функция и что она, фактически,
делает. В нашей программе мы передаем ей обычный список языка Python. В
действительности же, все входные данные должны соответствовать массивам пакета numpy, то есть, иметь
тип:
numpy.array
Поэтому,
указанный список можно сначала преобразовать в массив numpy:
import numpy as np
y = np.array([1, 2, -6, 0, 4])
А, затем, передать его функции plot():
Визуально,
результат будет тем же. Вообще, почти все функции пакета matplotlib работают именно
с массивами numpy: принимают их в
качестве аргументов или возвращают. Поэтому при работе с matplotlib желательно
знать основы numpy. Если у вас
есть пробелы в этих знаниях, то смотрите плейлист по этой теме:
https://www.youtube.com/watch?v=eDuuKvIWzew&list=PLA0M1Bcd0w8zmegfAUfFMiACPKfdW4ifD
Итак, указывая
всего один аргумент в функции plot() он интерпретируется как множество
точек по ординате (координате Oy). Соответственно, координата x формируется
автоматически как индексы элементов массива y:
Но мы можем
значения по абсциссе указывать и самостоятельно, например, так:
x = np.array([4, 5, 6, 7, 8])
y = np.array([1, 2, -6, 0, 4])
plt.plot(x, y)
Теперь значения
по оси Ox будут лежать в
диапазоне от 4 до 8. Причем, функция plot() при
отображении этих данных делает одну простую вещь – она соединяет прямыми линиями
точки с указанными координатами:
Но это значит,
если указать точки в узлах квадрата, то будет нарисован квадрат на плоскости?
Давайте проверим. Запишем следующие координаты:
x = np.array([1, 1, 5, 5, 1])
y = np.array([1, 5, 5, 1, 1])
plt.plot(x, y)
И действительно,
видим квадрат в координатных осях. Также это означает, что мы можем рисовать
графики с разными шагами по оси абсцисс, например, так:
y = np.arange(0, 5, 1) # [0, 1, 2, 3, 4]
x = np.array([a*a for a in y]) # [ 0, 1, 4, 9, 16]
plt.plot(x, y)
В результате, мы
увидим не прямую линию, а изогнутую:
Вот так гибко и
интуитивно понятно обрабатывает функция plot() входные
данные.
Давайте сразу на
график наложим сетку, чтобы он выглядел более информативно. Для этого достаточно
прописать строчку:
Далее, если нам
нужно в этих же осях отобразить еще один график, то это можно сделать так:
y = np.arange(0, 5, 1)
x = np.array([a*a for a in y])
y2 = [0, 1, 2, 3]
x2 = [i+1 for i in y2]
plt.plot(x, y, x2, y2)
Причем, оба
графика отображаются совершенно независимо. В частности, они здесь имеют разное
число точек. Тем не менее, никаких проблем не возникает и мы видим следующую
картину:
Это потрясающая
гибкость пакета matplotlib значительно облегчает жизнь
инженерам-программистам. Здесь не надо задумываться о таких мелочах, как
согласованность данных. Все будет показано так, как сформировано.
Соответственно,
указывая следующие пары в функции plot(), будут
отображаться все новые и новые графики в текущих координатах. Но можно сделать
и по-другому. Вызвать функцию plot() несколько раз подряд, например:
plt.plot(x, y)
plt.plot(x2, y2)
Получим
аналогичный эффект – два графика в одних координатах. Такая реализация возможна
благодаря объектно-ориентированной архитектуре пакета matplotlib. Здесь
координатные оси – это объект Axes. Соответственно, вызывая функцию plot() снова и
снова, в этот объект помещают новые и новые данные для каждого отдельного
графика:
Но откуда взялся
объект Axes, если мы его
нигде не создавали? Все просто. Он создается автоматически при первом вызове
функции plot(), если ранее,
до этого не было создано ни одного Axes. А раз
создается система координат, то создается и объект Figure, на котором
размещаются оси. Поэтому в нашей программе, при первом вызове функции plot() было создано
два объекта:
- Figure – объект для
отображения всех данных, связанных с графиком;
- Axes – двумерная
координатная ось декартовой системы.
Позже мы увидим,
как можно самостоятельно создавать эти объекты и использовать при оформлении графиков.
А пока продолжим рассмотрение базовых возможностей функции plot().
Изменение стилей линий у графиков
Если третьим
параметром в plot() указать
строку с двумя дефисами:
то график будет
изображен не сплошной линией, а штрихами. Какие еще варианты типа линий
возможны? Они приведены в следующей таблице:
Обозначение
типа линии
|
Описание
|
'-'
|
Непрерывная
линия (используется по умолчанию)
|
'--'
|
Штриховая
линия
|
'-.'
|
Штрихпунктирная
линия
|
':'
|
Пунктирная
линия
|
'None' или ' '
|
Без
рисования линии
|
Например, для
второго графика мы можем указать пунктирную линию:
Функция plot возвращает
список на объекты Line2D. Если записать вызов в виде:
lines = plt.plot(x, y, '--')
print(lines)
то в консоли
увидим список из одного объекта, так как функция отображает один график. Через
этот объект можно непосредственно управлять графиком, например, поменять тип
линии:
plt.setp(lines, linestyle='-.')
Здесь
используется еще одна функция setp() для настройки свойств объектов, в
данном случае линейного графика.
Если же мы
отобразим два графика одной функцией plot():
lines = plt.plot(x, y, '--', x2, y2, ':')
то коллекция lines будет содержать
два объекта Line2D. Далее,
назначим им стиль:
plt.setp(lines, linestyle='-.')
Теперь они оба
будут отображены штрихпунктирной линией.
Изменение цвета линий графиков
Помимо типа
линий у графиков, конечно же, можно менять и их цвет. В самом простом варианте
достаточно после стиля указать один из символов предопределенных цветов:
<p align=center>{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}
Цвет можно
понять по английскому названию указанной первой буквы. Например,
b = blue, r = red, g = green, c = cyan, w = white, и т.д.
Давайте изменим
цвет у наших графиков, указав символы g и m:
lines = plt.plot(x, y, '--g', x2, y2, ':m')
Как видите, все
предельно просто. Или же можно использовать именованный параметр color (или просто
букву c) для более
точной настройки цвета:
lines = plt.plot(x, y, '--g', x2, y2, ':m', color='r')
В данном случае
оба графика будут отображены красным. Преимущество этого параметра в
возможности указания цвета не только предопределенными символами, но, например,
в шестнадцатиричной записи:
lines = plt.plot(x, y, '--g', x2, y2, ':m', color='#0000CC')
Или в виде
кортежей формата:
RGB и RGBA
lines = plt.plot(x, y, '--g', x2, y2, ':m', color=(0, 0, 0))
lines = plt.plot(x, y, '--g', x2, y2, ':m', c=(0, 0, 0, 0.5))
В последней строчке
использовано второе имя параметра color. Это основные
способы задания цветов. Причем, не только для типов линий графиков, но и при
работе с другими объектами пакета matplotlib. Так что эта
информация в дальнейшем нам еще пригодится.
Изменение маркеров точек у графиков
Наконец, можно
поменять тип маркеров у точек. Для этого в форматную строку достаточно
прописать один из предопределенных символов. Например, вот такая запись:
отображает
график с круглыми точками:
Какие типы
маркеров еще могут быть? Они перечислены в таблице ниже:
Обозначение
|
Описание
маркера
|
'o'
|
|
'v'
|
|
'^'
|
|
'<'
|
|
'>'
|
|
'2'
|
|
'3'
|
|
'4'
|
|
's'
|
|
'p'
|
|
'*'
|
|
'h'
|
|
'H'
|
|
'+'
|
|
'x'
|
|
'D'
|
|
'd'
|
|
'|'
|
|
'_'
|
|
Используются все
эти символы очевидным образом. Причем, записывать их можно в любом порядке с
другими форматными символами:
lines = plt.plot(x, y, '-go', x2, y2, 's:m')
отобразится
следующий график:
Другой способ
определения маркера – использование параметра marker:
lines = plt.plot(x, y, '-go', x2, y2, 's:m', marker='d')
В этом случае
для обоих графиков будет присвоен один и тот же маркер типа 'd'. Для задания
цвета маркера, отличного от цвета линии, применяется параметр markerfacecolor:
lines = plt.plot(x, y, '-go', x2, y2, 's:m', marker='d', markerfacecolor='w')
Здесь мы выбрали
белый цвет заливки и графики теперь выглядят так:
Именованные параметры функций setp() и plot()
Все эти же
действия по оформлению графика можно выполнять и с помощью функции setp(). Например,
записав следующую строчку:
plt.setp(lines[0], linestyle='-.', marker='s', markerfacecolor='b', linewidth=4)
получим
отображение графика штрихпунктирной линией, квадратным маркером с синей
заливкой и толщиной линии, равной 4 пиксела. Какие еще именованные параметры есть
у функций setp() и plot()? В таблице
ниже я привел основные из них:
Параметр
|
Описание
|
alpha
|
Степень
прозрачности графика (значение от 0 до 1)
|
color
или c
|
Цвет
линии
|
dash_capstyle
|
Стиль
штриховых конечных точек ['butt' | 'round' | 'projecting']
|
dash_joinstyle
|
Стиль
штриховых соединительных точек ['miter' | 'round' | 'bevel']
|
data
|
Данные
графика в формате (x, y), где x, y – массивы numpy
|
linestyle
или ls
|
Стиль
линии [ '-' | '--' | '-.' | ':' | 'steps' | ...]
|
linewidth
или lw
|
Толщина
линии (вещественное число)
|
marker
|
Маркер
точек
|
markeredgecolor
или mec
|
Цвет
границ маркеров
|
markeredgewidth
или
mew
|
Толщина
границы маркеров (вещественное число)
|
markerfacecolor
или mfc
|
Цвет
заливки маркеров
|
markersize
или ms
|
Размер
маркеров
|
solid_capstyle
|
Стиль
конечных точек непрерывной линии ['butt' | 'round' | 'projecting']
|
solid_joinstyle
|
Стиль
соединительных точек непрерывной линии ['miter' | 'round' | 'bevel']
|
visible
|
Показать/скрыть
график [True | False]
|
xdata
|
Значения
для оси абсцисс (массив numpy)
|
ydata
|
Значения
для оси ординат (массив numpy)
|
Более подробную
информацию о параметрах для оформления графиков смотрите в документации по matplotlib.
Заливка областей графика
Наконец, можно
делать заливку областей графика с помощью функции:
fill_between(x,
y1, y2=0, where=None, interpolate=False, step=None, *, data=None,
**kwargs)
Основные
параметры здесь следующие:
- x, y1 – массивы
значений координат x и функции y1;
- y2 – массив (или
число) для второй кривой, до которой производится заливка;
- where – массив
булевых элементов, который определяет области для заливки.
В самом простом
случае эту функцию можно использовать так:
x = np.arange(-2*np.pi, 2*np.pi, 0.1)
y = np.cos(x)
plt.plot(x, y)
plt.fill_between(x, y)
plt.show()
У нас получилась
косинусоида с заливкой между значениями функции y и осью абсцисс y2 = 0. Если
третьим параметром указать другое число, отличное от нуля, например, 0,5:
plt.fill_between(x, y, 0.5)
то получим
следующий эффект:
А если
дополнительно еще сделать ограничение на выбор заливаемого региона, когда y < 0:
plt.fill_between(x, y, 0.5, where=(y < 0))
то получим такую
картину:
Также можно
вызвать эту функцию два раза подряд:
plt.fill_between(x, y, where=(y < 0), color='r', alpha=0.5)
plt.fill_between(x, y, where=(y > 0), color='g', alpha=0.5)
и сформировать
следующее оформление графика косинусоиды:
Вот так можно с
помощью функции plot() отображать графики в координатных осях и делать их
простое оформление.