在Python Matplotlib中绘制跨子图的网格
Matplotlib是Python中最受欢迎的数据可视化库之一。 它能够让用户用少量代码创建复杂的绘图,是公认的Python绘图领域的标准库。在实际应用中,有时候需要将多个图形分成不同的格子进行展示,而且格子之间需要跨行或跨列。本文介绍如何在Python Matplotlib中绘制跨子图的网格。
简单的网格
Matplotlib提供了一种称为subplot(子图)的方法,该方法使我们可以将多个小图像以网格的形式堆叠在一起。 如果图形区域被分为M * N网格,那么可以通过(i,j)编号来引用每个子区域。 Matplotlib的“plt.subplot()”命令接受三个参数:M表示子图的行数,N表示子图的列数,L表示子图的顺序。下面是一个简单的例子:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.figure(figsize=(10,10))
plt.subplot(2, 2, 1)
plt.plot(x, y)
plt.subplot(2, 2, 2)
plt.hist(y)
plt.subplot(2, 2, 3)
plt.scatter(x, y)
plt.subplot(2, 2, 4)
plt.plot(x, y**2)
plt.show()
代码中,我们创建了一个2×2的网格,并将四个图形放在不同的位置。第一个图形是一条曲线,第二个图形是一个直方图,第三个图形是一组散点图,第四个图形是平方的曲线。当运行代码时,我们将看到分开的四个图形。
尽管MATPLOTLIB的子图处理非常好用,也很强大,但是在实际应用中,常常需要将多个子图合并成一个大图(即跨子图)。不过这种需求并不在.subplot的方案中,所以我们需要用到另外一组微调函数,即plt.subplots_adjust()。
跨行的网格
Matplotlib的“subplot2grid()”方法允许灵活地绘制具有不同行和列的网格。大多数人只知道“subplot()”方法,但“subplot2grid()”是更高级的方法,支持更多自定义选项,特别是跨行列的操作,让我们可以很自如地做出好看的网格图。
绘制简单的跨行网格
让我们来看一下如何在网格中定义跨行。subplot2grid()
方法接受的第一个元素是值为(M, N)的元组(其中M和N分别为子图网格的行和列),第二个参数是(x, y),他表示子区域的左下角所在的单元格位置。最后一个参数是 colspan 表示子图所跨越的列数。
下面是一个简单的跨行的网格例子:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig = plt.figure(figsize=(10,4))
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
ax1.plot(x, y)
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
ax2.hist(y)
ax3 = plt.subplot2grid((3,3), (1,2), rowspan=2)
ax3.scatter(x, y)
ax4 = plt.subplot2grid((3,3), (2,0), colspan=2)
ax4.plot(x, y**2)
plt.subplots_adjust(hspace=0.5, wspace=0.5)
plt.show()
在这个例子中,我们定义了一个3×3的网格,分为9个小区域。我们在子区域(0,0)上绘制了一条正弦曲线。在子区域(1,0)中绘制了正弦值的直方图。在子区域(1,2)中绘制了正弦值的散点图。最后,在子区域(2,0)上绘制了正弦值的平方曲线。我们使用“plt.subplots_adjust”命令更好地适应大图。
间距调整
为了让子图之间更加紧密和舒适,可以在“subplots_adjust”中指定列和行之间的距离。
代码中,hspace
和wspace
参数控制相邻子图(行、列)之间的空白距离。 例如,distance=0.1将在行和列之间添加10%的额外空间。下面是一个例子:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig = plt.figure(figsize=(10,4))
ax1 = fig.add_subplot(3, 3, 1)
ax1.plot(x, y)
ax2 = fig.add_subplot(3, 3, 2)
ax2.hist(y)
ax3 = fig.add_subplot(3, 3, 3)
ax3.scatter(x, y)
ax4 = fig.add_subplot(3, 3, 4)
ax4.plot(x, y**2)
ax5 = fig.add_subplot(3, 3, 5)
ax5.plot(x, y)
ax6 = fig.add_subplot(3, 3, 6)
ax6.hist(y)
ax7 = fig.add_subplot(3, 3, 7)
ax7.scatter(x, y)
ax8 = fig.add_subplot(3, 3, 8)
ax8.plot(x, y**2)
ax9 = fig.add_subplot(3, 3, 9)
ax9.plot(x, y)
plt.subplots_adjust(hspace=0.5, wspace=0.5)
plt.show()
在这个例子中,我们定义了一个3×3的网格,分为9个小区域。我们使用 “fig.add_subplot()”命令和一个“for”循环生成每个子区域。我们使用“subplots_adjust”命令更好地适应大图。
跨列的网格
Matplotlib的“subplot2grid()”方法还允许指定子图宽度和高度(即跨列操作)。在跨越多列时,将行跨保持在1,并在“subplot2grid()”方法的最后一个参数中指定希望跨越的列数。下面是一个简单的跨列的网格例子:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig = plt.figure(figsize=(10,4))
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
ax1.plot(x, y)
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
ax2.hist(y)
ax3 = plt.subplot2grid((3,3), (1,2), rowspan=2)
ax3.scatter(x, y)
ax4 = plt.subplot2grid((3,3), (2,0), colspan=2)
ax4.plot(x, y**2)
plt.subplots_adjust(hspace=0.5, wspace=0.5)
plt.show()
在这个例子中,我们定义了一个3×3的网格,分为9个小区域。我们在子区域(0,0)上绘制了一条正弦曲线。在子区域(1,0)中绘制了正弦值的直方图。在子区域(1,2)中绘制了正弦值的散点图。最后,在子区域(2,0)上绘制了正弦值的平方曲线。跨行在上面的例子中我们已经讲到过了,这里我们重点关注跨列操作。
我们可以通过“colspan”参数指定一个网格单元子图所占的列数。在第2行第1列单元格的子图中,我们使用“colspan=2”的参数将绘图“ax2”设置在相邻的两个列中,它将占用0,1行,0到1列。 另外,第三行的第一列单元格子图使用“rowspan=2”参数将它设置在相邻的两个行中,它将占用1,2行,2列。
结论
在Python Matplotlib中绘制跨子图的网格可以用到的参数有:M,N(行列),rowspan、colspan(跨行跨列),支持高度自定义的子图处理方法让我们能够自由灵活地布置各个子区域的位置、大小和数量。Matplotlib的广泛使用和良好的文档使得它成为绘制数据可视化的常用工具。