Когда я использовал подзаголовок и пытался использовать следующий подзаговор для построения только одной фигуры, он выдавал ошибку:
AttributeError: 'AxesSubplot' object has no attribute 'flat'
fig, ax = plt.subplots(nrows=nrows, ncols=ncols,figsize=figsize)
for i, ax in enumerate(ax.flat):
ax.plot(X, Y, color='k')
Как решить эту проблему, если я хочу произвольно установить количество подцифр? Как мне легко понять ax.flat?






flat — это атрибут массивов numpy, который возвращает итератор. Например, если у вас есть такой двумерный массив:
import numpy as np
arr2d = np.arange(4).reshape(2, 2)
arr2d
# array([[0, 1],
# [2, 3]])
атрибут flat предоставляется как удобный способ перебора этого массива, как если бы это был массив 1d:
for value in arr2d.flat:
print(value)
# 0
# 1
# 2
# 3
Вы также можете сгладить массив с помощью метода flatten:
arr2d.flatten()
# array([0, 1, 2, 3])
Итак, возвращаясь к вашему вопросу, когда вы указываете:
ncols к 1 и nrows к значению больше 1 или наоборот, вы получаете оси в массиве 1d numpy, и в этом случае атрибут flat возвращает тот же массив.ncols, так и nrows до значений больше 1, вы получаете оси в массиве 2d, и в этом случае атрибут flat возвращает плоский массив.ncols и nrows равны 1, вы получаете объект осей, у которого нет атрибута flat.Таким образом, возможным решением было бы каждый раз превращать ваш объект ax в массив numpy:
fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)
ax = np.array(ax)
for i, axi in enumerate(ax.flat):
axi.plot(...)
Когда вы создаете набор подграфиков с несколькими строками/столбцами с помощью команды fig,ax=plt.subplots(), он возвращает fig и список осей ax. Форма списка ax имеет 2 измерения (строки, столбцы). Вот почему вам нужно сгладить его, чтобы он стал 1 измерением, когда вы повторяете список ax. Чтобы получить доступ к определенным осям, вам нужны индексы строк/столбцов, например, ax[r][c] — это оси в (r+1)-й строке/(c+1)-м столбце. Индексы отсчитываются от нуля. Рабочий код ниже демонстрирует, как это сделать.
import matplotlib.pyplot as plt
import numpy as np
nrows,ncols = 3,2
figsize = [5,9]
X = np.random.rand(6)
Y = np.random.rand(6)
fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)
for i, axi in enumerate(ax.flat):
axi.plot(X, Y, color='k')
rowid = i // ncols
colid = i % ncols
axi.set_title("row:"+str(rowid)+",col:"+str(colid))
# You can access the axes by row_id, col_id.
# Now let's plot on ax[row_id][col_id] of your choice
ax[0][1].plot(Y,X,color='red') # plot 2nd line in red
ax[2][0].plot(Y,X,color='green') # plot 2nd line in green
plt.tight_layout(True)
plt.show()
Выходной график:
Есть ровно один случай, когда код
fig, ax = plt.subplots(nrows=nrows, ncols=ncols,figsize=figsize)
for i, ax in enumerate(ax.flat):
ax.plot(X, Y, color='k')
не будет работать, как ожидалось. Это для nrows = ncols = 1. Это связано с тем, что для одной строки и столбца ax является одним подзаголовком, а не массивом из нескольких подзаголовков.
Чтобы обойти эту проблему и иметь возможность использовать один и тот же код, не зная заранее nrows и ncols, используйте параметр squeeze=False. Это гарантирует, что ax всегда будет массивом и, следовательно, будет иметь атрибут .flat. Для лучшего понимания не называйте массив осей тем же именем, что и сами оси.
fig, axs = plt.subplots(nrows=nrows, ncols=ncols, squeeze=False, figsize=figsize)
for i, ax in enumerate(axs.flat):
ax.plot(X, Y, color='k')