Что здесь происходит?
После создания трех временных столбцов (рядов), мы определили одну фигуру (fig), содержащую один объект Axes (plot, ax);
Мы вызываем методы ax напрямую для создания диаграммы с разбивкой по областям и добавлением легенды, заголовка и ярлыка оси y. С ОО-подходом, становится ясно, что все это – атрибуты ах;
tight_layout() применяется к объекту Figure в целом для очистки пробелов;
Давайте рассмотрим пример, в котором содержится несколько малых графиков (Axes) внутри одного объекта Figure, формирующих два коррелированных массива, выводящихся из дискретного равномерного распределения:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randint(low=1, high=11, size=50)
y = x + np.random.randint(1, 5, size=x.size)
data = np.column_stack((x, y))
fig, (ax1, ax2) = plt.subplots(
nrows=1, ncols=2,
figsize=(8, 4)
)
ax1.scatter(x=x, y=y, marker='o', c='r', edgecolor='b')
ax1.set_title('Scatter: $x$ versus $y$')
ax1.set_xlabel('$x$')
ax1.set_ylabel('$y$')
ax2.hist(
data, bins=np.arange(data.min(), data.max()),
label=('x', 'y')
)
ax2.legend(loc=(0.65, 0.8))
ax2.set_title('Frequencies of $x$ and $y$')
ax2.yaxis.tick_right()
plt.show()
|
В данном примере происходит больше, чем на первый взгляд:
Так как мы создаем фигуру «1×2», полученный результат от plt.subplots(1, 2) теперь является объектом Figure и массивом NumPy объектов Axes. (Вы можете проверить это при помощи fig, axs = plt.subplots(1, 2), и взглянуть на оси);
Мы имеем дело с ax1 и ax2 индивидуально. (Случай, когда использование объектно-ориентированного подхода будет весьма трудным.) Последняя строка – это хорошее изображение иерархии объектов, где мы модифицируем принадлежащую второму объекту Axes ось y, разместив галочки и отметки справа;
Текст внутри знака доллара использует разметку TeX для выделения переменных курсивом.
Обратите внимание на то, что несколько объектов Axes могут «принадлежать» или быть переданными данной фигуре. В данном примере (строчные, а не прописные объекты Axes – не спорим, терминология здесь слегка запутанная), дает нам список всех объектов Axes:
Python
1
|
(fig.axes[0] is ax1, fig.axes[1] is ax2) # (True, True)
|
Сделав еще один шаг вглубь, мы можем создать фигуру, которая содержит сетку объектов Axes 2х2 в качестве альтернативы:
Python
1
|
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(7, 7))
|
Так, а это за «ax»? Теперь это не одиночный объект Axes, но их двухмерный массив NumPy:
Python
1
2
3
|
print(type(ax)) # numpy.ndarray
print(ax)
|
Результат:
Python
1
2
3
4
5
|
array([[,
],
[,
]],
dtype=object)
|
Python
1
|
print(ax.shape) # (2, 2)
|
Это подтверждается в документации:
«ax» может быть как одним объектом matplotlib.axes.Axes, так и массивом объектов Axes в более чем одном созданном малом графике.
Сейчас нам нужно вызвать методы создания графиков для каждого из этих объектов Axes (не массива NumPy, который является просто контейнером). Простой способ передать эти объекты, это использовать итеративную распаковку после выравнивания массива как одномерного:
Python
1
2
|
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(7, 7))
ax1, ax2, ax3, ax4 = ax.flatten()
|
Мы также могли бы выполнить это при помощи ((ax1, ax2), (ax3, ax4)) = ax, но первый подход более гибкий.
Для демонстрации более продвинутых функций меньших графиков, давайте добавим немного данных о макроэкономике недвижимости в Калифорнии, извлеченной из сжатого архива tar, пользуясь io, tarfile, и urllib из стандартной библиотеки Python.
Python
1
2
3
4
5
6
7
8
9
10
|
from io import BytesIO
import tarfile
from urllib.request import urlopen
url = 'http://www.dcc.fc.up.pt/~ltorgo/Regression/cal_housing.tgz'
b = BytesIO(urlopen(url).read())
fpath = 'CaliforniaHousing/cal_housing.data'
with tarfile.open(mode='r', fileobj=b) as archive:
housing = np.loadtxt(archive.extractfile(fpath), delimiter=',')
|
Переменная «response» оси y, указанная ниже, использует термин из статистики: среднюю стоимость недвижимости. pop и age обозначают население и средний возраст недвижимости, соответственно.
Python
1
2
|
y = housing[:, -1]
pop, age = housing[:, [4, 7]].T
|
Далее, давайте определим «вспомогательную функцию», которая размещает текстовый бокс внутри графика и выполняет функцию «заголовка внутри графика»:
Python
1
2
3
4
5
6
7
|
def add_titlebox(ax, text):
ax.text(.55, .8, text,
horizontalalignment='center',
transform=ax.transAxes,
bbox=dict(facecolor='white', alpha=0.6),
fontsize=12.5)
return ax
|
Теперь мы готовы к тому, чтобы сделать реальный график. Модуль gridspec нашей библиотеки matplotlib открывает расширенные возможности для настройки объектов под графиком. subplot2grid() отлично взаимодействует с этим модулем. Скажем, мы хотим создать такой макет:
Выше, у нас есть сетка 3х2. ax1 в два раза выше и шире ax2 и ax3. Это значит, что она занимает два ряда и две строки.
Второй аргумент, принадлежащий subplot2grid() – это (ряд, строка) локация объекта Axes со следующей сеткой:
Python
1
2
3
4
5
6
7
8
9
|
import matplotlib.pyplot as plt
gridsize = (3, 2)
fig = plt.figure(figsize=(12, 8))
ax1 = plt.subplot2grid(gridsize, (0, 0), colspan=2, rowspan=2)
ax2 = plt.subplot2grid(gridsize, (2, 0))
ax3 = plt.subplot2grid(gridsize, (2, 1))
plt.show()
|
Теперь мы можем перейти к привычному режиму, настраивая каждый объект Axes индивидуально:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ax1.set_title(
'Home value as a function of home age & area population',
fontsize=14
)
sctr = ax1.scatter(x=age, y=pop, c=y, cmap='RdYlGn')
plt.colorbar(sctr, ax=ax1, format='$%d')
ax1.set_yscale('log')
ax2.hist(age, bins='auto')
ax3.hist(pop, bins='auto', log=True)
add_titlebox(ax2, 'Histogram: home age')
add_titlebox(ax3, 'Histogram: area population (log scl.)')
|
Выше, colorbar() (который отличается от ColorMap) вызывается напрямую к объекту Figure, а не к Axes. Его первый аргумент – это результат ax1.scatter(), который выполняет функцию отображения переменных оси y в ColorMap.
Визуально, разница в цветах незначительна (говоря о переменной у), так как мы рассматриваем ось у, указывающую на влияние возраста недвижимости на её стоимость.
Достарыңызбен бөлісу: |