Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Лекция №5. работа с ГРАФИКОЙ в python
СОДЕРЖАНИЕ
5.1 Введение matplotlib
5.2 Отображение данных на графике
5.3 Как правильно строить графики
5.1 Введение в matplotlib
Библиотека matplotlib предназначена для создания научной графики.
1. График линии
Метод построения линии очень прост:
• есть массив абсцис (x);
• есть массив ординат (y);
• элементы с одинаковым индексом в этих массивах - это координаты точек на плоскости;
• последовательные точки соединяются линией.
Под массивами, подразумеваются списки, кортежи или массивы NumPy.
Выполним следующий код:
import matplotlib.pyplot as plt
plt.plot((0, 1, 2, 3, 4, 5, 6, 7), (0, 3, 1, 2, 1, 5, 4, 0))
plt.show()
В результате получим вот такой простой график:
Метод plt.plot(), в простейшем случае, принимает один аргумент - последовательность чисел, которая соответствует оси ординат (y), ось абсцис (x) строится автоматически от 0 до n, где n - это длинна массива ординат.
Следующий код построит точно такой же график:
import matplotlib.pyplot as plt
plt.plot((0, 3, 1, 2, 1, 5, 4, 0))
plt.show()
Такой способ может оказаться полезным, если диапазон чисел на оси абцис для вас не важен. Однако, если диапазон или шаг все-таки важны, то их все же необходимо указать:
Выполним следующий код:
import matplotlib.pyplot as plt
plt.plot((-4, -3, -2, -1, 0, 1, 2, 3), (0, 3, 1, 2, 1, 5, 4, 0))
plt.show()
2. График множества точек
Единственное отличие графика множества точек от графика линии - точки не соединяются линией.
import matplotlib.pyplot as plt
plt.scatter([0, 1, 2, 3, 4 , 5], [0, 1, 2, 3, 4 , 5])
plt.show()
Все как и прежде двум соответствующим значениям из массивов соответствуют координаты точки.
Если у вас несколько множеств, то все их так же можно построить на одном графике:
import matplotlib.pyplot as plt
plt.scatter([0, 1, 2, 3, 4 , 5], [0, 1, 2, 3, 4 , 5])
plt.scatter([1, 2, 3, 1, 2 , 1], [2, 3, 4, 3, 4 , 4])
plt.scatter([2, 3, 4, 3, 4 , 4], [1, 2, 3, 1, 2 , 1])
plt.show()
3. Гистограммы
Очень часто, данные удобно представлять в виде гистограмм. В самом простом случае, гистограмма - это множество прямоугольников, площадь которых (или высота) пропорциональна какой-нибудь величине. Например, осадки за 3 месяца: в июне выпало 10 мм, в июле - 15мм, в августе - 21 мм.
import matplotlib.pyplot as plt
plt.bar([6, 7, 8], [10, 15, 21])
plt.show()
Первый массив содержит номера месяцев, а второй массив - значения показателей. Эти прямоугольники построены вертикально, но их можно отображать и в горизонтальном виде:
Пример 1.
import matplotlib.pyplot as plt
plt.barh([6, 7, 8], [10, 15, 21])
plt.show()
Пример 2.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
cars = ('Bugatti Chiron', 'Hennessey Venom F5', 'Koenigsegg Agera RS')
y = np.arange(len(cars))
speeds = [420,435,457]
ax.barh(y, speeds, align='center',
color='kyr', ecolor='black')
ax.set_yticks(y)
ax.set_yticklabels(cars)
ax.invert_yaxis()
ax.set_xlabel('Top Speed (km/h)')
plt.subplots_adjust(left=0.3)
plt.show()
Гистограммы могут отображать несколько наборов данных, что очень удобно для их сравнения:
import matplotlib.pyplot as plt
plt.bar([6, 7, 8], [10, 15, 21])
plt.bar([6, 7, 8], [6, 12, 21])
plt.show()
Такой график мог бы отображать летние осадки за два года. Но вот в чем дело, прямоугольники строятся поверх друг друга и если они равны, как в случае наших осадков за август, то прямоугольники друг друга перекроют. Если указать небольшое смещение по оси x, то ситуация не улучшится:
import matplotlib.pyplot as plt
plt.bar([6, 7, 8], [10, 15, 21])
plt.bar([6.5, 7.5, 8.5], [6, 12, 28])
plt.show()
График станет привлекательней, если сузить прямоугольники и расположить их без наложения друг на друга:
import matplotlib.pyplot as plt
plt.bar([5.9, 6.9, 7.9], [10, 15, 21], width = 0.2)
plt.bar([6.1, 7.1, 8.1], [6, 12, 28], width = 0.2)
plt.show()
4. Круговые диаграммы
Если вам необходимо наглядно отобразить соотношение частей целого, то лучше воспользоваться круговой диаграммой. Например, в компании работают 50 человек из них 40 женщи и 10 мужчин:
import matplotlib.pyplot as plt
plt.pie([40, 10])
plt.show()
Все предельно просто - количество элементов в массиве определяет количество клиньев, а величина значений определяет их площадь:
Пример 1.
import matplotlib.pyplot as plt
plt.pie([5, 13, 21, 27, 10, 17])
plt.show()
Пример 2.
import matplotlib.pyplot as plt
labels = 'Dalmatians', 'Beagles', 'Labradors', 'German Shepherds'
sizes = [6, 10, 15, 9]
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%.1f%%')
plt.show()
Пример 3.
import matplotlib.pyplot as plt
labels = '20-25','25-30','30-35','35-40','40-45','45-50'
sizes = [31.4,18.6,28.1,11.9,5.3,4.7]
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%.1f%%')
plt.show()
Пример 4.
import matplotlib.pyplot as plt
labels = 'Dalmatians', 'Beagles', 'Labradors', 'German Shepherds'
sizes = [6, 10, 15, 9]
explode = (0.1, 0, 0, 0)
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%.1f%%', shadow=True, startangle=90)
ax.set_aspect('equal')
plt.show()
5.2 Отображение данных на графике
1. Основные компоненты matplotlib
MPL очень большая библиотека, но по своей сути она состоит из небольшого количества базовых компонентов:
Figure - это контейнер самого верхнего уровня, та область на которой все нарисовано. Таких областей может быть несколько, каждая из которых может содержать несколько контейнеров Axes.
Axes - это та область на которой чаще всего и отражаются графики (данные в виде графиков), а так же все вспомогательные атрибуты (линии сетки, метки, указатели и т.д.). Часто, установка этой области сопровождается с вызовом subplot, который и помещает Axes на регулярную сетку. Поэтому, так же часто Axes и Subplot можно считать синонимами.
Каждая область Axes содержит XAxis и YAxis. Они содержат, деления, метки и прочие вспомогательные атрибуты
2. Отображение данных на графике
Большинство графиков: линий, гистограмм, круговых диаграмм т.е. отображений данных происходит на Axes. Поэтому, для рисования на Axes необходимо использовать какой-нибудь из его методов. К слову сказать, этих методов целая куча, но мы сосредоточимся всего на двух: plot и scatter.
• plot рисует точки соединенные линиями;
• scatter просто рисует точки
Давайте построим простой график на котором будет присутствовать отображение одних данных точками, а других линиями:
Пример 1.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([0, 1, 2, 3, 4], [0, 6, 7, 15, 19])
ax.scatter([0, 1, 2, 3, 4], [1, 3, 8, 12, 27])
plt.show()
Нарисованные данные так же поддерживают самые разные параметры внешнего вида:
Пример 2.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([0, 1, 2, 3, 4], [0, 6, 7, 15, 19], color = 'black', linewidth = 5)
ax.scatter([0, 1, 2, 3, 4], [1, 3, 8, 12, 27], color = 'blue', marker = '*')
plt.show()
Параметры внешнего вида придется указывать (если надо) вместе с данными внутри ax.plot() и ax.scatter(). Это противоречит рекомендациям, но и в этом случае можно оформить код в более читаемый вид:
Пример 3.
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4]
y_1 = [0, 6, 7, 15, 19]
y_2 = [1, 3, 8, 12, 27]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y_1,
color = 'black',
linewidth = 5)
ax.scatter(x, y_2,
color = 'blue',
marker = '*')
plt.show()
3. Методы Axes и pyplot
Мы раньше создавали графики без всяких Figure и Axes. Дело в том что почти все методы axes присутствуют в модуле pyplot. Например, при вызове plt.title('spam') модуль pyplot вызывает ax.set_title('spam'). Можно сказать, что модуль pyplot создает Figure и Axes автоматически (хотя это не совсем так). Фактически мы можем переписать весь наш пример следующим образом:
import matplotlib.pyplot as plt
plt.plot([0, 1, 2, 3, 4], [0, 6, 7, 15, 19], linewidth = 3)
plt.scatter([0, 1, 2, 3, 4], [1, 3, 8, 12, 27], color = 'orange')
plt.show()
4. Несколько Axes на одной Figure
Очень часто, нам необходимо размещать несколько графиков рядом друг с другом. Это проще всего сделать используя plt.subplots(). Разберем следующий пример:
import matplotlib.pyplot as plt
fig = plt.figure()
ax_1 = fig.add_subplot(2, 2, 1)
ax_2 = fig.add_subplot(2, 2, 2)
ax_3 = fig.add_subplot(2, 2, 3)
ax_4 = fig.add_subplot(2, 2, 4)
ax_1.set(title = 'ax_1', xticks=[], yticks=[])
ax_2.set(title = 'ax_2', xticks=[], yticks=[])
ax_3.set(title = 'ax_3', xticks=[], yticks=[])
ax_4.set(title = 'ax_4', xticks=[], yticks=[])
plt.show()
В этом примере, так же как и раньше, мы сначала создали область Figure, а затем с помощью команды fig.add_subplot() начали добавлять, одну за другой область Axes (ax_1, ax_2, ax_3, ax_4). Причем заметьте, каждая область Axes является независимой от других, то есть на на них могут быть нарисованы самые разные графики и установлены самые разные параметры внешнего вида.
Теперь давайте немного разберемся с тем что делает метод add_subplot(). А делает он следующее, разбивает Figure на указанное количество строк и столбцов. После такого разбиения Figure можно представить как таблицу (или координатную сетку). Затем область Axes помещается в указанную ячейку. Для всего этого add_subplot() необходимо всего три числа, которые мы и передаем ему в качестве параметров:
• первое - количество строк;
• второе - количество столбцов
• третье - индекс ячейки.
Индексирование полученных ячеек начинается с левого верхнего угла, выполняется построчно слева-направо и заканчивается в правом нижнем углу:
import matplotlib.pyplot as plt
fig = plt.figure()
ax_1 = fig.add_subplot(3, 2, 1)
ax_2 = fig.add_subplot(3, 2, 2)
ax_3 = fig.add_subplot(3, 2, 3)
ax_4 = fig.add_subplot(3, 2, 4)
ax_5 = fig.add_subplot(3, 2, 5)
ax_6 = fig.add_subplot(3, 2, 6)
ax_1.set(title = 'ax_1', xticks=[], yticks=[])
ax_2.set(title = 'ax_2', xticks=[], yticks=[])
ax_3.set(title = 'ax_3', xticks=[], yticks=[])
ax_4.set(title = 'ax_4', xticks=[], yticks=[])
ax_5.set(title = 'ax_5', xticks=[], yticks=[])
ax_6.set(title = 'ax_6', xticks=[], yticks=[])
plt.show()
Заполнять областями Axes всю область Figure не обязательно:
import matplotlib.pyplot as plt
fig = plt.figure()
ax_1 = fig.add_subplot(3, 2, 1)
ax_2 = fig.add_subplot(3, 2, 4)
ax_3 = fig.add_subplot(3, 2, 5)
ax_1.set(title = 'ax_1', xticks=[], yticks=[])
ax_2.set(title = 'ax_2', xticks=[], yticks=[])
ax_3.set(title = 'ax_3', xticks=[], yticks=[])
plt.show()
Каждый отдельный вызов add_subplot() выполняет разбивку Figure, так как как указано в его параметрах и не зависит от предыдущих разбиений:
import matplotlib.pyplot as plt
fig = plt.figure()
ax_1 = fig.add_subplot(3, 1, 1)
ax_2 = fig.add_subplot(3, 2, 4)
ax_3 = fig.add_subplot(3, 3, 9)
ax_1.set(title = 'ax_1', xticks=[], yticks=[])
ax_2.set(title = 'ax_2', xticks=[], yticks=[])
ax_3.set(title = 'ax_3', xticks=[], yticks=[])
plt.show()
5. subplots()
Конечно, такой способ размещения некоторого количества областей Axes на Figure довольно гибок, но на практике функция plt.subplots(nrows, ncols) оказывается гораздо удобнее:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows = 2, ncols =2 )
axes[0,0].set(title='axes[0,0]')
axes[0,1].set(title='axes[0,1]')
axes[1,0].set(title='axes[1,0]')
axes[1,1].set(title='axes[1,1]')
for ax in axes.flat:
ax.set(xticks=[], yticks=[])
plt.show()
5.3 Как правильно строить графики
Как размещать несколько графиков вместе (несколько областей Axes на Figure) мы разобрались. Как теперь строить эти самые графики? Все довольно просто, после того как мы создали область Axes, которая по сути является объектом Python, мы можем воспользоваться любым из методов этого объекта, включая и те, которые занимаются отображением данных на этой области:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# Данные, которые хотим отобразить:
x1 = 10*np.random.rand(100) # координаты 'x'
y1 = 10*np.random.rand(100) # координаты 'y'
ax.scatter(x1, y1) # метод, отображающий данные в виде точек
# на плоскости
ax.set(title='Случайные точки') # метод, размещающий заголовок
# над "Axes"
plt.show()
При этом мы можем отображать на одной области Axes несколько наборов данных, как одинаковыми так и разными методами:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x1 = np.linspace(0, 10, 30)
y1 = np.random.beta(0.1, 0.6, size = 30)
x2 = np.linspace(11, 20, 30)
y2 = np.random.gamma(shape = 0.3, scale = 1.1, size = 30)
x3 = np.linspace(21, 30, 30)
y3 =np.random.pareto(3.5, size = 30)
# Данные в виде точек:
ax.scatter(x1, y1)
ax.scatter(x2, y2)
ax.scatter(x3, y3)
# Данные в виде линий:
ax.plot(x1, y1 + 3)
ax.plot(x2, y2 + 3)
ax.plot(x3, y3 + 3)
ax.set(title='Бетта, Гамма и Паретто распределения')
plt.show()
В случае, когда у нас несколько областей Axes, то отображение на них данных, ничем не отличается от случая единственной области. Однако, области Axes можно добавить двумя способами: add_subplot() и subplots(). Давайте рассмотрим случай add_subplot():
import numpy as np
import matplotlib.pyplot as plt
# Данные:
x = np.linspace(0, 10, 100)
y = np.sin(x)
img = y.reshape(5, 20)
# Создаем "Figure" и "Axes":
fig = plt.figure()
ax_1 = fig.add_subplot(2, 1, 1)
ax_2 = fig.add_subplot(2, 1, 2)
# Методы, отображающие данные:
ax_1.plot(x, y)
ax_2.imshow(img)
# Добавление заголовков:
ax_1.set(title = 'sin(x)')
ax_2.set(title = 'img')
plt.show()
1. Plot - график линии
Без преувеличения - это самый распространенный график и как он строится нам уже известно. Давайте разберемся с тем, как сделать эти графики более привлекательными.
Цвет линии
Цвет линии можно указать с помощью параметра color. Само значение цвета может быть из самых разных цветовых моделей:
import numpy as np
import matplotlib.pyplot as plt
x = np.zeros(8)
fig, ax = plt.subplots()
# RGB:
ax.plot(x, color = (0.9, 0.2, 0.9))
# RGBA:
ax.plot(np.arange(-1, 7),
color = (0.1, 0.2, 0.9, 0.5),
linewidth = 12)
# hex RGB:
ax.plot(x + 1, color = '#0a0b0c')
# hex RGBA:
ax.plot(x + 2, color = '#0a0b0c3a')
# уровень серого в интервале [0, 1]:
ax.plot(x + 3, color = '0.3')
# ключ цвета из {'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}:
ax.plot(x + 4, color = 'g')
# название цвета из X11/CSS4:
ax.plot(x + 5, color = 'indigo')
fig.set_figwidth(12)
fig.set_figheight(6)
fig.set_facecolor('mintcream')
ax.set_facecolor('whitesmoke')
plt.show()
Поддержка такого количества цветовых моделей позволяет выбирать именно ту, которая в данной ситуации наиболее удобна. Например, можно быстро установить цвет линии с помощью односимвольного ключа из {'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}, но готовя график для презентации или публикации удобнее использовать X11/CSS4. В случае, когда цвет из X11/CSS4 не подходит, смотрим код RGB и подгоняем.
Наклоненная линия, цвет которой задан в модели RGBA увеличена в ширине, для наглядности ее прозрачности. Ширина линии задается с помощью параметра linewidth. Этот параметр часто применяется при изменении начертания линии:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y = np.sin(x)
fig, ax = plt.subplots()
# Сплошная линия ('-' или 'solid',
# установлен по умолчанию):
ax.plot(x, y,
linestyle = '-',
linewidth = 1,
color = 'crimson')
# Пунктирная линия ('--' или 'dashed'):
ax.plot(x, y + 1,
linestyle = '--',
linewidth = 2,
color = 'darkmagenta')
# Точка-тире ('-.' или 'dashdot'):
ax.plot(x, y + 2,
linestyle = '-.',
linewidth = 4,
color = 'indigo')
# Точка-точка (':' или 'dotted'):
ax.plot(x, y + 3,
linestyle = ':',
linewidth = 6,
color = 'darkblue')
fig.set_figwidth(12)
fig.set_figheight(6)
fig.set_facecolor('linen')
ax.set_facecolor('ivory')
plt.show()
Тонкие пунктирные линии заставляют очень сильно напрягать зрение, но если слегка увеличить их ширину, то они воспринимаются гораздо легче. Улучшить восприятие линии можно так же с помощью маркеров:
import numpy as np
import matplotlib.pyplot as plt
x = np.zeros(10)
fig, ax = plt.subplots()
# Вид (marker)и размер маркера (markersize):
ax.plot(x,
marker = 'o',
color = 'seagreen')
ax.plot(x + 1,
marker = '^',
markersize = 10,
color = 'seagreen')
ax.plot(x + 2,
marker = 's',
markersize = 15,
color = 'seagreen')
ax.plot(x + 3,
marker = 'X',
markersize = 20,
color = 'seagreen')
# Цвет маркера (markerfacecolor),
# его края (markeredgecolor) и
# толщина его края (markeredgewidth):
ax.plot(x + 5,
marker = '^',
markersize = 20,
color = 'green',
markerfacecolor = 'lawngreen',
markeredgecolor = 'darkgreen',
markeredgewidth = 3)
ax.plot(x + 6,
marker = 's',
markersize = 20,
color = 'lime',
linewidth = 4,
markerfacecolor = 'lawngreen',
markeredgecolor = 'limegreen',
markeredgewidth = 5)
ax.plot(x + 7,
marker = 'X',
markersize = 20,
color = 'teal',
markerfacecolor = 'greenyellow',
markeredgecolor = 'teal',
markeredgewidth = 3)
fig.set_figwidth(12)
fig.set_figheight(6)
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
2. Scatter - график разброса (точки)
График разброса - это тоже очень распространенный график. Как правило, именно глядя на него, начинаешь понимать, что в данных есть что-то любопытное. И как правило, этот график практически никогда не требует никакого изменения своего внешнего вида. Но иногда, наглядность данных сильно снижается из-за небольших размеров графика, а так же размеров и цветов используемых маркеров.
Цвет точек
Цвет линии можно указать с помощью параметра c. Само значение цвета может быть из самых разных цветовых моделей.
Точки одного цвета:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(1000) # x - координаты точек
y = np.random.rand(1000) # y - координаты точек
fig, ax = plt.subplots()
ax.scatter(x, y,
c = 'deeppink') # цвет точек
ax.set_facecolor('black') # цвет области Axes
ax.set_title('Один цвет') # заголовок для Axes
fig.set_figwidth(8) # ширина и
fig.set_figheight(8) # высота "Figure"
plt.show()
Если вы хотите поместить на одном графике разные наборы данных, то каждому такому набору можно сопоставить свой цвет точек:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(1000)
y1 = np.random.gamma(1, size = 1000)
y2 = np.random.gamma(2, size = 1000)
y3 = np.random.gamma(4, size = 1000)
y4 = np.random.gamma(8, size = 1000)
fig, ax = plt.subplots()
# ключ цвета из {'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}:
ax.scatter(x, y1,
c = 'r')
# RGB:
ax.scatter(x + 1, y2,
c = [[0.1, 0.63, 0.55]])
# hex RGB:
ax.scatter(x + 2, y3,
c = '#ad09a3')
# уровень серого в интервале [0, 1]:
ax.scatter(x + 3, y4,
c = ['0.9'])
ax.set_facecolor('black')
ax.set_title('Один цвет')
fig.set_figwidth(8) # ширина и
fig.set_figheight(8) # высота "Figure"
plt.show()
Здесь можно увидеть два недостатка. Первый - это слишком большие точки, которые накладываются друг на друга и небольшой размер самого графика. Контролировать размер точек можно с помощью параметра s:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(5000)
y1 = np.random.gamma(1, size = 5000)
y2 = np.random.gamma(2, size = 5000)
y3 = np.random.gamma(4, size = 5000)
y4 = np.random.gamma(8, size = 5000)
fig, ax = plt.subplots()
# ключ цвета из {'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}:
ax.scatter(x, y1,
c = 'r',
s = 1)
# RGB:
ax.scatter(x + 1, y2,
c = [[0.1, 0.63, 0.55]],
s = 1)
# hex RGB:
ax.scatter(x + 2, y3,
c = '#ad09a3',
s = 1)
# уровень серого в интервале [0, 1]:
ax.scatter(x + 3, y4,
c = ['0.9'],
s = 1)
ax.set_facecolor('black')
ax.set_title('Один цвет')
# Увеличим размер графика:
fig.set_figwidth(14)
fig.set_figheight(14)
plt.show()
Как видите, мы разместили на графике 20000 точек, но от уменьшения размера точек и увеличения размеров самого графика он только выиграл в наглядности. Может показаться странным, но такие небольшие трюки могут очень сильно помочь вашей интуиции.
Второй недостаток - наложение точек друг на друга. Мы можем и не уменьшать размер самих точек, а добавить к их цвету прозрачности, зачастую, это тоже добавляет наглядности:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(5000)
y1 = np.random.gamma(1, size = 5000)
y2 = np.random.gamma(2, size = 5000)
y3 = np.random.gamma(4, size = 5000)
y4 = np.random.gamma(8, size = 5000)
fig, ax = plt.subplots()
# RGBA:
ax.scatter(x, y1,
c = [[1, 0, 0, 0.05]])
# RGBA:
ax.scatter(x + 1, y2,
c = [[0.1, 0.63, 0.55, 0.05]])
# hex RGBA:
ax.scatter(x + 2, y3,
c = '#ad09a305')
# RGBA:
ax.scatter(x + 3, y4,
c = [[0.5, 0, 0.5, 0.05]])
ax.set_title('Прозрачные точки')
fig.set_figwidth(8) # ширина и
fig.set_figheight(8) # высота "Figure"
plt.show()
3. Bar - гистограмма
Гистограммы устроены очень просто, но изменяя различные параметры мы можем отобразить с их помощью очень много информации, а так же повысить как наглядность данных так и привлекательность самого графика.
Ширина прямоугольников
Чаще всего мы строим гистограммы из одиночных наборов данных, в таких случаях мы можем обойтись, вообще, без каких бы то ни было изменений графика. Просто строим одну или несколько гистограмм на одной области Figure:
Пример 1.
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y = np.random.randint(1, 20, size = 7)
fig, ax = plt.subplots()
ax.bar(x, y)
ax.set_facecolor('seashell')
fig.set_facecolor('floralwhite')
fig.set_figwidth(12) # ширина Figure
fig.set_figheight(6) # высота Figure
plt.show()
Пример 2.
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
n = 5
milan= (73, 43, 44, 70, 61)
inter = (54, 59, 69, 46, 58)
fig, ax = plt.subplots()
index = np.arange(n)
bar_width = 0.35
opacity = 0.9
ax.bar(index, milan, bar_width, alpha=opacity, color='r',
label='Milan')
ax.bar(index+bar_width, inter, bar_width, alpha=opacity, color='b',
label='Inter')
ax.set_xlabel('Seasons')
ax.set_ylabel('Points')
ax.set_title('Milan v/s Inter')
ax.set_xticks(index + bar_width / 2)
ax.set_xticklabels(('1995-96','1996-97','1997-98','1998-99','1999-00'
))
ax.legend()
plt.show()
Пример 3.
import numpy as np
import matplotlib.pyplot as plt
x1 = np.arange(1, 8)
y1 = np.random.randint(1, 20, size = 7)
x2 = np.arange(1, 101)
y2 = np.random.randint(1, 20, size = 100)
fig, axes = plt.subplots(2, 1)
axes[0].bar(x1, y1)
axes[1].bar(x2, y2)
axes[0].set_facecolor('seashell')
axes[1].set_facecolor('seashell')
fig.set_facecolor('floralwhite')
fig.set_figwidth(12) # ширина Figure
fig.set_figheight(6) # высота Figure
plt.show()
Ширина прямоугольников подбирается автоматически и нас это, вполне, устраивает. Но если мы имеем дело с несколькими наборами данных, которые нужно отобразить в пределах одной области Axes, то прямоугольники начинают перекрывать друг друга:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y1 = np.random.randint(1, 10, size = 7)
y2 = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
ax.bar(x, y1)
ax.bar(x, y2)
ax.set_facecolor('seashell')
fig.set_figwidth(12) # ширина Figure
fig.set_figheight(6) # высота Figure
fig.set_facecolor('floralwhite')
plt.show()
В таких случаях, нам необходимо вручную задавать ширину с помощью параметра width и смещение прямоугольников в массиве x:
import numpy as np
import matplotlib.pyplot as plt
# Задаем смещение равное половине ширины прямоугольника:
x1 = np.arange(1, 8) - 0.2
x2 = np.arange(1, 8) + 0.2
y1 = np.random.randint(1, 10, size = 7)
y2 = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
ax.bar(x1, y1, width = 0.4)
ax.bar(x2, y2, width = 0.4)
ax.set_facecolor('seashell')
fig.set_figwidth(12) # ширина Figure
fig.set_figheight(6) # высота Figure
fig.set_facecolor('floralwhite')
plt.show()
В некоторых ситуациях ширина прямоугольников, так же как и их высота, может быть пропорциональна некоторой величине. Что бы задать ширину каждого отдельного прямоугольника можно указать параметр width в виде массива чисел:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
width_rectangle = np.random.rand(7)
ax.bar(x, y, width = width_rectangle)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Пример 4.
import numpy as np
import matplotlib.pyplot as plt
n = 3
china = (16,21,23)
malaysia = (21,11,21)
x = np.arange(n)
width = 0.35
p1 = plt.bar(x, malaysia, width, color='b')
p2 = plt.bar(x, china, width, color='r', bottom=malaysia)
plt.ylabel('Points')
plt.title('China v/s Malaysia')
plt.xticks(x, ('Round 1', 'Round 2', 'Round 3'))
plt.yticks(np.arange(0, 60, 5))
plt.legend((p2[0], p1[0]), ('China', 'Malaysia'))
plt.show()
Выравнивание нижнего края прямоугольников
Разместить несколько гистограмм на одной области Axes можно не только с помощью горизонтального смещения и изменения ширины прямоугольников, но и с помощью параметра bottom, который задает значение по которому выравнивается нижний край прямоугольников:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y1 = np.random.randint(1, 10, size = 7)
y2 = np.random.randint(1, 10, size = 7)
y3 = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
ax.bar(x, y1)
ax.bar(x, y2, bottom = 11)
ax.bar(x, y3, bottom = 21)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Выравнивание для каждого прямоугольника можно задать с помощью массива:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 51)
y = np.random.randint(1, 50, size = 50)
fig, ax = plt.subplots()
bottom_rectangle = np.random.randint(30, size = 50)
ax.bar(x, y, bottom = bottom_rectangle)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Для того что бы состыковать прямоугольники нескольких наборов данных, достаточно выровнять одни прямоугольники по значениям других:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
data_1 = np.random.randint(2, 15, size = 7)
data_2 = np.random.randint(3, 20, size = 7)
fig, ax = plt.subplots()
ax.bar(x, data_1)
ax.bar(x, data_2, bottom = data_1)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Цвет
Для того что бы задать цвет всех прямоугольников достаточно указать его в параметре color:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
ax.bar(x, y, color = 'red')
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Так же возможно задать цвет каждого отдельного прямоугольника, указав в параметре color массив цветов:
Пример 5.
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
color_rectangle = np.random.rand(7, 3) # RGB
ax.bar(x, y, color = color_rectangle)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Matplotlib поддерживает разные цветовые модели и форматы. Задавая цвет в модели RGBA вы можете контролировать прозрачность прямоугольников, что так же позволяет размещать несколько наборов данных, но без смещения:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y1 = np.random.randint(1, 10, size = 7)
y2 = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
color_rectangle = np.random.rand(7, 3) # RGB
ax.bar(x, y1, color = color_rectangle, width = 0.5)
color_rectangle = np.random.rand(7, 4) # RGBA
color_rectangle[:,3] = 0.5
ax.bar(x, y2, color = color_rectangle)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')
plt.show()
Если вам необходимо выделить границу прямоугольников, то вы можете задать ее цвет (edgecolor) и толщину (linewidth):
Пример 6.
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1, 8)
y = np.random.randint(1, 10, size = 7)
fig, ax = plt.subplots()
ax.bar(x, y,
color = 'chartreuse',
edgecolor = 'darkblue',
linewidth = 5)
fig.set_figwidth(12) # ширина и
fig.set_figheight(6) # высота "Figure"
ax.set_facecolor('darkslateblue')
plt.show()
Пример 7.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
cars = ('Bugatti Chiron', 'Hennessey Venom F5', 'Koenigsegg Agera RS')
y = np.arange(len(cars))
speeds = [420,435,457]
ax.barh(y, speeds, align='center',
color='kyr', ecolor='black')
ax.set_yticks(y)
ax.set_yticklabels(cars)
ax.invert_yaxis()
ax.set_xlabel('Top Speed (km/h)')
plt.subplots_adjust(left=0.3)
plt.show()
Заголовки графиков
Добавить заголовок к области Axes можно с помощью метода set_title(label, fontdict=None, loc='center', pad=None, **kwargs), который принимает четыре позиционных аргумента и целую кучу аргументов по ключу. В простейшем случае, мы просто указываем заголовок в виде строки:
import numpy as np
import matplotlib.pyplot as plt
data = np.random.normal(0, 1, 10000)
fig, ax = plt.subplots()
ax.hist(data, bins = 50, rwidth = 0.4)
ax.set_title('Нормальное распределение')
plt.show()
Параметр fontdict не очень удобен и редко используется, в тоже время параметры loc и pad позволяют ,быстро задать горизонтальное и вертикальное выравнивание:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 3)
for ax in axes:
mu = 10*np.random.random()
kappa = 10*np.random.random()
data = np.random.vonmises(mu, kappa, size=1000)
ax.hist(data, bins = 50, rwidth = 0.4)
# Вертикальное и горизонтальное выравнивание заголовков:
axes[0].set_title('loc = "left", pad = 0',
loc = 'left',
pad = 0) # задает расстояние в точках
axes[1].set_title('loc = "center", pad = 10',
loc = 'center', # значение по умолчанию
pad = 10)
axes[2].set_title('loc = "right", pad = 20',
loc = 'right',
pad = 20)
fig.set_figheight(2)
fig.set_figwidth(14)
plt.show()
Параметр fontsize устанавливает размер шрифта, а параметры color и backgroundcolor его цвет и цвет области фона заголовка:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2)
for ax in axes:
mu = 10*np.random.random()
kappa = 10*np.random.random()
data = np.random.vonmises(mu, kappa, size=1000)
ax.hist(data, bins = 50, rwidth = 0.4)
# Размер шрифта его цвет и цвет фона:
axes[0].set_title('fontsize = 20',
fontsize = 20,
color = 'red',
backgroundcolor = 'black')
axes[1].set_facecolor('black')
axes[1].set_title('fontsize = 15',
fontsize = 15,
color = 'white',
backgroundcolor = 'black')
fig.set_figheight(2)
fig.set_figwidth(14)
plt.show()
Установить вид шрифта и его начертание можно с помощью параметров fontfamily и fontstyle:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 3)
for ax in axes:
mu = 10*np.random.random()
kappa = 10*np.random.random()
data = np.random.vonmises(mu, kappa, size=1000)
ax.hist(data, bins = 50, rwidth = 0.4)
# Вид и начертание шрифта заголовка:
axes[0].set_title('Заголовок',
fontfamily = 'serif',
fontstyle = 'italic',
fontsize = 30)
axes[1].set_title('Заголовок',
fontfamily = 'fantasy',
fontstyle = 'oblique',
fontsize = 30)
axes[2].set_title('Заголовок',
fontfamily = 'monospace',
fontstyle = 'normal',
fontsize = 30)
fig.set_figheight(2)
fig.set_figwidth(14)
plt.show()
Добавление легенды
Легенда - это помощник, позволяющий определить что соответствует определенному цвету линии или прямоугольника. Лучше пояснить на примере:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y1 = np.sin(x) - 2
y2 = np.cos(x) + 2
y3 = np.sinc(x)
fig, ax = plt.subplots()
ax.plot(x, y1, label = 'sin(x)')
ax.plot(x, y2, label = 'cos(x)')
ax.plot(x, y3, label = r'$\frac{sin(x)}{x}$')
ax.legend()
fig.set_figheight(5)
fig.set_figwidth(8)
plt.show()
Легенда сделала график более информативным, хотя сама нуждается в некоторых улучшениях. Но сначала разберемся как она вообще у нас появилась. Во первых, мы добавили параметр label в каждом методе plot() - этот параметр содержит текст отображаемый в легенде. Во вторых мы добавили еще один метод legend, который собственно и помещает легенду на область Axes.
Позиционирование легенды можно установить с помощью параметра loc. по умолчанию этот параметр установлен в значение 'best', что соответствует наилучшему расположению, но это не всегда так. Иногда, положение необходимо установить вручную, для чего имеется еще 10 дополнительных параметров:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y1 = np.sin(x)
fig, axes = plt.subplots(5, 2)
location = ['upper right', 'upper left', 'lower left',
'lower right', 'right', 'center left',
'center right', 'lower center', 'upper center', 'center']
i = 0
for ax in axes.ravel():
ax.plot(x, y1, label = 'sin(x)')
ax.legend(loc = location[i])
ax.set_title(location[i])
ax.set_xticks([])
ax.set_yticks([])
i += 1
fig.set_figheight(10)
fig.set_figwidth(10)
plt.show()
Параметр shadow устанавливает тень легенды и убирает ее прозрачность, а fontsize устанавливает размер шрифта:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y = np.sin(x)
fig, axes = plt.subplots(1, 2)
axes[0].plot(x, y, label = 'sin(x)')
axes[0].legend(shadow = True,
fontsize = 15)
axes[0].set_title('shadow = True')
axes[1].plot(x, y, label = 'sin(x)')
axes[1].legend(shadow = False,
fontsize = 15)
axes[1].set_title('shadow = False')
fig.set_figwidth(8)
fig.set_figheight(4)
plt.show()
На самом деле, мы практически не ограничены в настройке внешнего вида легенды:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 10)
y1 = 2*x + 5
y2 = -x + 8
y3 = 0.5*x + 5
y4 = np.full(10, 5)
fig, ax = plt.subplots()
ax.plot(x, y1, label = 'y = 2x + 5')
ax.plot(x, y2, label = 'y = -x + 8')
ax.plot(x, y3, label = 'y = 0.5x + 5')
ax.plot(x, y4, label = 'y = 5')
ax.legend(fontsize = 25,
ncol = 2, # количество столбцов
facecolor = 'oldlace', # цвет области
edgecolor = 'r', # цвет крайней линии
title = 'Прямые', # заголовок
title_fontsize = '20' # размер шрифта заголовка
)
fig.set_figwidth(12)
fig.set_figheight(12)
plt.show()
6.4. Добавление сетки
Порой, простое добавление сетки в разы увеличивает легкость восприятия графика. С сеткой гораздо легче соотносить определенные области графика с значениями на его осях. В самом простом случае, сетка добавляется методом Axes.grid():
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y = np.sinc(x)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.grid()
plt.show()
С помощью параметра axis мы можем выбирать какие именно линии сетки необходимо отображать: горизонтальные, вертикальные или все вместе:
#axis
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y = np.sinc(x)
fig = plt.figure()
ax_1 = fig.add_subplot(2, 1, 1)
ax_2 = fig.add_subplot(2, 2, 3)
ax_3 = fig.add_subplot(2, 2, 4)
ax_1.plot(x, y)
ax_1.grid(axis = 'x')
ax_1.set_title('axis = "x"')
ax_2.plot(x, y)
ax_2.grid(axis = 'y')
ax_2.set_title('axis = "y"')
ax_3.plot(x, y)
ax_3.grid(axis = 'both')
ax_3.set_title('axis = "both"')
fig.set_figwidth(12)
fig.set_figheight(12)
plt.show()
Так как сетка состоит из линий, то метод grid() поддерживает все параметры уже знакомые нам по графику plot(). Мы можем легко установить такие параметры как цвет линий, их толщину и начертание:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y = np.sinc(x)
fig, ax = plt.subplots()
ax.plot(x, y, linewidth = 5)
ax.grid(color = 'blue', # цвет линий
linewidth = 2, # толщина
linestyle = '--') # начертание
fig.set_figwidth(12)
fig.set_figheight(6)
plt.show()
Линии сетки бывают как основные так и вспомогательные. Контролировать то как они отображаются отдельно позволяет параметр which. Данный параметр может принимать одно из трех значений:
• 'major' - применение параметров внешнего вида к основным линиям (установлен по умолчанию);
• 'minor' - к вспомогательным линиям;
• 'both' - к обеим линиям.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3*np.pi, 3*np.pi, 200)
y = np.sinc(x)
fig, ax = plt.subplots()
ax.plot(x, y,
color = 'r',
linewidth = 4)
# Прежде чем рисовать вспомогательные линии
# необходимо включить второстепенные деления
# осей:
ax.minorticks_on()
# Определяем внешний вид линий основной сетки:
ax.grid(which='major',
color = 'k',
linewidth = 2)
# Определяем внешний вид линий вспомогательной
# сетки:
ax.grid(which='minor',
color = 'k',
linestyle = ':')
fig.set_figwidth(12)
fig.set_figheight(6)
plt.show()
Добавление линий
Иногда бывает необходимо добавить на график вертикальную или горизонтальную линию. Это можно сделать с помощью методов Axes.vlines и Axes.hlines:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y = (x - 2)*(x + 2)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.grid()
# Вертикальные линии:
ax.vlines(0, y.min(), y.max())
ax.vlines(-2, y.min(), y.max(), color = 'r')
ax.vlines(2, y.min(), y.max(), color = 'r')
# Горизонтальные динии:
ax.hlines(0, -5, 5)
ax.hlines(-4, -5, 5)
plt.show()
Данные методы имеют всего три ключевых аргумента. Для hlines() - это y - точка на оси y через которою пройдет горизонтальная линия; xmin - начало линии; xmax - конец линии.
Добавление текста
Что бы добавить на график какой-то поясняющий текст можно воспользоваться методом Axes.text():
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y1 = (x - 2)*(x + 2)
y2 = 2*x + 5
fig, ax = plt.subplots()
ax.plot(x, y1)
ax.plot(x, y2)
# Добавляем текст:
ax.text(0, 9, 'прямая',
rotation = 38,
fontsize = 20)
ax.text(1.5, 2, 'парабола',
rotation = 50,
fontsize = 20)
fig.set_figwidth(8)
fig.set_figheight(8)
plt.show()
В простейшем случае, метод text(), принимает всего три параметра: x и y - координаты левого верхнего края области с текстом, и, s - строка с текстом. Так же существует очень много других параметров, которые позволяют настроить внешний вид области с текстом.
Подписи осей
Очень часто оси графика должны быть снабжены каким-то поясняющим текстом. Добавить его можно с помощью методов Axes.set_xlabelAxes.set_ylabel:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 100)
y = x*(x - 2)*(x - 4)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.grid()
# Добавляем подписи к осям:
ax.set_xlabel('время (с)')
ax.set_ylabel('скорость (м/с)')
plt.show()
Деления осей и подписи к ним
Также как и линии сетки, деления осей бывают основными и вспомогательными. Для управления делениями осей - тиками необходим модуль matplotlib.ticker. Однако, чаще всего, без сетки, от этих делений нет никакого толка. Вот график с вспомогательными делениями без сетки:
import numpy as np
import matplotlib.pyplot as plt
# Подключаем модуль управления тиками:
import matplotlib.ticker as ticker
x = np.linspace(-10, 10, 200)
y = 0.01*(x + 9)*(x + 6)*(x - 6)*(x - 9)*x
fig, ax = plt.subplots()
ax.plot(x, y, color = 'r', linewidth = 3)
# Устанавливаем интервал основных делений:
ax.xaxis.set_major_locator(ticker.MultipleLocator(2))
# Устанавливаем интервал вспомогательных делений:
ax.xaxis.set_minor_locator(ticker.MultipleLocator(1))
# Тоже самое проделываем с делениями на оси "y":
ax.yaxis.set_major_locator(ticker.MultipleLocator(50))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))
fig.set_figwidth(12)
fig.set_figheight(8)
plt.show()
Текстовые подписи делений осей
Очень часто, работая с временными рядами или количественными показателями нам необходимо менять подписи осей. Если это временные ряды, то подписи должны отражать дату и время, если это количественные показатели, то подписями должны служить имена рассматриваемых объектов. Например:
import numpy as np
import matplotlib.pyplot as plt
month = ('май', 'июнь', 'июль', 'август', 'сентябрь')
value = (12, 24, 18, 11, 6)
position = np.arange(5)
fig, ax = plt.subplots()
ax.bar(position, value)
# Устанавливаем позиции тиков:
ax.set_xticks(position)
# Устанавливаем подписи тиков
ax.set_xticklabels(['май', 'июнь', 'июль', 'август', 'сентябрь'])
fig.set_figwidth(10)
fig.set_figheight(6)
plt.show()
Но как видите, такие подписи тиков нуждаются в улучшении читаемости и внешнего вида. Чаще всего достаточно увеличить размер шрифта, но не менее часто, люди зациклены на том что подписи должны быть именно снизу, что приводит к наложению подписей друг на друга.
Самый простой выход - это горизонтальное размещение графика, и, если возможно, расстановке переносов:
import numpy as np
import matplotlib.pyplot as plt
labels = ['Контрольная\nгруппа № %i' % i for i in range(1, 6)]
value = (12, 24, 18, 11, 6)
position = np.arange(5)
fig, ax = plt.subplots()
ax.barh(position, value)
# Устанавливаем позиции тиков:
ax.set_yticks(position)
# Устанавливаем подписи тиков
ax.set_yticklabels(labels,
fontsize = 15)
fig.set_figwidth(10)
fig.set_figheight(6)
plt.show()