在单个循环中使用子图在多个图形上绘制

4

我需要在一个循环内绘制两个图,每个图都有多个子图。以下是当只有一个图时的操作:

我正在进行绘图,其中包括两个图形,每个图形都有多个子图。我需要在单个循环内完成此操作。当只有一个图形时,我执行以下操作:

fig, ax = plt.subplots(nrows=6,ncols=6,figsize=(20, 20))
fig.subplots_adjust(hspace=.5,wspace=0.4)
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

for x in range(1,32):
    plt.subplot(6,6,x)
    plt.title('day='+str(x))
    plt.scatter(x1,y1)
    plt.scatter(x2,y2)
    plt.colorbar().set_label('Distance from ocean',rotation=270)
plt.savefig('Plots/everyday_D color.png')    
plt.close()

现在我知道当你有多个图形时,你需要像这样做:

fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()

但我不知道如何在循环中绘制图表,以便每个子图都在其位置上(因为如果有两个图形,则不能继续执行plt.scatter)。 请具体说明我需要做什么(关于是fig1.scatter、ax1.scatter、fig.subplots_adjust等,以及如何在最后保存和关闭)

但我不知道如何在循环中绘制图表,以便每个子图都在其位置上(因为如果有两个图形,则不能继续执行plt.scatter)。请具体说明我需要做什么(关于是fig1.scatter、ax1.scatter、fig.subplots_adjust等,以及如何在最后保存和关闭)
2个回答

4

每个pyplot函数都有其对象导向API中对应的方法。如果你真的想同时循环遍历两个图形的轴,代码应该是这样的:

import numpy as np
import matplotlib.pyplot as plt

x1 = x2 = np.arange(10)
y1 = y2 = c = np.random.rand(10,6)

fig1, axes1 = plt.subplots(nrows=2,ncols=3)
fig1.subplots_adjust(hspace=.5,wspace=0.4)

fig2, axes2 = plt.subplots(nrows=2,ncols=3)
fig2.subplots_adjust(hspace=.5,wspace=0.4)

for i, (ax1,ax2) in enumerate(zip(axes1.flatten(), axes2.flatten())):
    ax1.set_title('day='+str(i))
    ax2.set_title('day='+str(i))
    sc1 = ax1.scatter(x1,y1[:,i], c=c[:,i])
    sc2 = ax2.scatter(x2,y2[:,i], c=c[:,i])
    fig1.colorbar(sc1, ax=ax1)
    fig2.colorbar(sc2, ax=ax2)

plt.savefig("plot.png") 
plt.show()   
plt.close()

在这里,您需要循环遍历两个扁平化的轴数组,以便ax1ax2是要绘制的matplotlib轴fig1fig2是matplotlib图形(matplotlib.figure.Figure)。
为了获得索引,使用了enumerate。因此,该行为:
for i, (ax1,ax2) in enumerate(zip(axes1.flatten(), axes2.flatten())):
    # loop code

这里的“等同于”与之相当。
for i in range(6):
    ax1 = axes1.flatten()[i]
    ax2 = axes2.flatten()[i]
    # loop code

或者
i = 0
for ax1,ax2 in zip(axes1.flatten(), axes2.flatten()):
    # loop code
    i += 1

需要写更多的内容。

你可能会对使用面向对象的API解决方案更加灵活和可取感兴趣,但仍然有可能使用纯pyplot解决方案。这将类似于:

import numpy as np
import matplotlib.pyplot as plt

x1 = x2 = np.arange(10)
y1 = y2 = c = np.random.rand(10,6)

plt.figure(1)
plt.subplots_adjust(hspace=.5,wspace=0.4)

plt.figure(2)
plt.subplots_adjust(hspace=.5,wspace=0.4)

for i in range(6):
    plt.figure(1)
    plt.subplot(2,3,i+1)
    sc1 = plt.scatter(x1,y1[:,i], c=c[:,i])
    plt.colorbar(sc1)

    plt.figure(2)
    plt.subplot(2,3,i+1)
    sc2 = plt.scatter(x1,y1[:,i], c=c[:,i])
    plt.colorbar(sc2)

plt.savefig("plot.png") 
plt.show()   
plt.close()

谢谢你的回答。我明白enumerate基本上是在for循环中创建索引。那么ax1和ax2只是索引吗?你能解释一下这个例子中ax1、axes1和fig1是什么类型的对象吗? - Dr proctor
ax1ax2是Matplotlib的轴。enumerate是在循环中获取索引的简单方法。也许这个链接对于更好地理解enumerate有所帮助。我也更新了答案。 - ImportanceOfBeingErnest

1
这里有一个版本,展示了如何在两个不同的图表上运行散点图。基本上,您需要引用使用 plt.subplots 创建的坐标轴。
import matplotlib.pyplot as plt
import numpy as np

x1 = y1 = range(10)
x2 = y2 = range(5)

nRows = nCols = 6
fig1, axesArray1 = plt.subplots(nrows=nRows,ncols=nCols,figsize=(20, 20))
fig1.subplots_adjust(hspace=.5,wspace=0.4)
fig1.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

fig2, axesArray2 = plt.subplots(nrows=nRows,ncols=nCols,figsize=(20, 20))
fig2.subplots_adjust(hspace=.5,wspace=0.4)
fig2.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

days = range(1, 32)
dayRowCol = np.array([i + 1 for i in range(nRows * nCols)]).reshape(nRows, nCols)
for day in days:
    rowIdx, colIdx = np.argwhere(dayRowCol == day)[0]

    axis1 = axesArray1[rowIdx, colIdx]
    axis1.set_title('day=' + str(day))
    axis1.scatter(x1, y1)

    axis2 = axesArray2[rowIdx, colIdx]
    axis2.set_title('day=' + str(day))
    axis2.scatter(x2, y2)

    # This didn't run in the original script, so I left it as is
    # plt.colorbar().set_label('Distance from ocean',rotation=270)

fig1.savefig('plots/everyday_D1_color.png')
fig2.savefig('plots/everyday_D2_color.png')
plt.close('all')

当我从帖子中获取原始代码时,plt.colorbar() 引发了一个错误,因此我在答案中省略了它。如果您有colorbar 的工作示例,我们可以看看如何使其适用于两个图像,但其他代码应按预期工作!
请注意,如果 daydayRolCol 中没有出现,Numpy 将引发错误,由您决定如何处理该情况。此外,使用 Numpy 绝不是唯一的方法,只是我熟悉的一种方法 - 您真正需要做的就是找到将特定日期/图与要绘制轴的 (x, y) 索引相关联的方法。

如果您回答了一个已经有答案的问题,最好明确指出您的回答与现有答案的不同之处。只是再提供一遍相同的解决方案没有用处。另外,其他答案展示了如何使用colorbar,所以我认为声称“我们”可以查看它是没有意义的 - 只有你自己想看的话才需要。 - ImportanceOfBeingErnest
谢谢您的回复。我的一个问题是,axis1和axis2是从哪里来的?它们似乎与您之前介绍的axesArray1没有任何联系(或者这只是一个错误)? - Dr proctor
@ImportanceOfBeingErnest 你说得对,另一个答案出现时我正在写我的答案,直到之后我才看到它。 - Eric
@Drproctor axis1 是通过以下方式从 axesArray1 创建的:axis1 = axesArray1[rowIdx, colIdx]axis2 也是以类似的方式创建的。 - Eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接