Сюжет Python используется для отображения одной фигуры - PullRequest
0 голосов
/ 22 марта 2019

Когда я использовал субплот и пытался использовать следующий субплот для построения только одной фигуры, он выдаст ошибку:

AttributeError: объект 'AxesSubplot' не имеет атрибута '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?

Ответы [ 4 ]

2 голосов
/ 23 марта 2019

Существует только один случай, когда код

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')
0 голосов
/ 22 марта 2019

Когда вы создаете набор вспомогательных участков с несколькими строками / столбцами с помощью команды 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()

Выходной участок:

enter image description here

0 голосов
/ 23 марта 2019

Вы можете использовать либо ax.ravel(), либо ax.flatten(). Ниже приведен простой пример

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 6))

# for i, ax in enumerate(ax.flatten()):
for i, ax in enumerate(ax.ravel()):
    ax.plot([1,2,3], color='k')
plt.show()

enter image description here

0 голосов
/ 22 марта 2019

flat - это атрибут numpy массивов, который возвращает итератор. Например, если у вас есть 2d массив, подобный этому:

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(...)
...