在数据可视化领域subplot是一个非常实用的工具,它可以帮助我们在同一个图像中展示多个子图,从而更好地呈现数据的分布、变化等信息。而对于使用Matplotlib等可视化库来进行数据分析的人员来说,如何使用subplot进行多个子图的绘制则是一个必须要掌握的技能。本篇文章就将围绕“如何使用subplot在matplotlib中绘制多个子图”来进行探讨,为大家介绍一些常用的绘图方法和技巧。
一、subplot基本用法
在matplotlib中使用subplot函数可以轻松地实现多个子图的绘制。subplot函数是一个带有三个参数的函数,分别为 numRows、numCols 和 plotNumber。其中numRows和numCols分别用于指定网格的行数和列数,plotNumber用于指定第几个子图,其取值范围为从左到右,从上到下的编号。例如,当 numRows=2, numCols=3时,plotNumber的范围为1-6。
在使用subplot绘制多个子图时,我们通常采用以下两种方式:
1.逐个画子图
具体实现方式是,首先创建一个大的画布,然后在这个画布上从左到右、从上到下逐个绘制子图。例如,以下代码创建了一个2x3的画布,并在其中绘制了6个子图,每个子图都是一个纵轴上的sin函数。
```
import matplotlib.pyplot as plt
import numpy as np
# 创建一个2x3的画布,并设置画布大小为(10, 6)
fig, ax = plt.subplots(2, 3, figsize=(10, 6))
# 分别绘制第1至第6个子图
x = np.linspace(-np.pi, np.pi, 100)
ax[0, 0].plot(x, np.sin(x)) # 第1个子图
ax[0, 1].plot(x, np.sin(2 * x)) # 第2个子图
ax[0, 2].plot(x, np.sin(3 * x)) # 第3个子图
ax[1, 0].plot(x, np.sin(4 * x)) # 第4个子图
ax[1, 1].plot(x, np.sin(5 * x)) # 第5个子图
ax[1, 2].plot(x, np.sin(6 * x)) # 第6个子图
# 显示图像
plt.show()
```
由于每个子图的大小和位置是固定的,所以该方法不适合绘制需要不停添加、删除子图的情况。
2.使用for循环一次性绘制多个子图
若要实现同时绘制多个子图,则可以使用for循环,将所有子图的绘制任务放在循环体内进行。具体实现方式是,首先确定子图的行数和列数,然后计算出子图的总数,最后使用for循环逐一绘制每个子图。例如,以下代码同样创建了一个2x3的画布,并在其中绘制了6个子图,每个子图同样也是一个纵轴上的sin函数。
```
import matplotlib.pyplot as plt
import numpy as np
# 定义子图的行数、列数和总数
numRows, numCols = 2, 3
numSubplots = numRows * numCols
# 创建一个2x3的画布,并设置画布大小为(10, 6)
fig, ax = plt.subplots(numRows, numCols, figsize=(10, 6))
# 循环绘制每个子图
x = np.linspace(-np.pi, np.pi, 100)
for i in range(numSubplots):
row = i // numCols
col = i % numCols
ax[row, col].plot(x, np.sin((i+1) * x))
# 显示图像
plt.show()
```
由于该方法使用了循环,所以可以方便地添加或删除子图,并且也可以自定义每个子图的大小和位置。
二、subplot高级用法
除了以上基本用法外,subplot还有一些更高级的用法。下面介绍两种常用的高级用法。
1.使用边距(margin)和间距(hspace、wspace)控制子图的位置和大小
margin指的是子图周围的留白区域,hspace和wspace分别指的是子图之间的纵向和横向的间距。通过调整这些参数,我们可以更加灵活地控制子图的位置和大小。例如,以下代码创建了一个类似4x4串口通信的画布,其中子图1和子图13占据了两行,每行三个子图的位置,它们的高度为两行的总高度的2/3,宽度则是其他子图的1.5倍。而子图7则占据了整个画布的最后一行,高度为总高度的1/3,宽度等于其他子图的宽度。其它子图则按照4x4的排布方式摆放。
```
import matplotlib.pyplot as plt
import numpy as np
# 设置画布尺寸
plt.figure(figsize=(10, 6))
# 定义每个子图的宽度、高度和位置
width_ratios = [1.5, 1, 1, 1]
height_ratios = [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1]
left_margin = 0.05
right_margin = 0.95
top_margin = 0.95
bottom_margin = 0.05
# 设置画布边距和间距
plt.subplots_adjust(
left=left_margin,
bottom=bottom_margin,
right=right_margin,
top=top_margin,
wspace=0.1,
hspace=0.1
)
# 绘制第1个子图
sub1 = plt.subplot2grid(
(14, 4),
(0, 0),
rowspan=2,
colspan=3,
fig=plt.gcf(),
)
# 绘制第7个子图
sub2 = plt.subplot2grid(
(14, 4),
(4, 0),
rowspan=4,
colspan=4,
fig=plt.gcf(),
)
# 绘制第13个子图
sub3 = plt.subplot2grid(
(14, 4),
(10, 0),
rowspan=2,
colspan=3,
fig=plt.gcf(),
)
# 循环绘制其它子图
for i in range(2, 13):
row = i // 4
col = i % 4
sub = plt.subplot2grid(
(14, 4),
(row + 2, col),
rowspan=1 if i != 8 else 2,
colspan=1 if i != 8 else 2,
fig=plt.gcf()
)
sub.set_xticks([])
sub.set_yticks([])
# 显示图像
plt.show()
```
2.使用gridspec绘制复杂子图布局
除了使用subplot2grid进行绘制之外,还可以使用gridspec绘制更加复杂的子图布局。gridspec实现了更高级别的子图布局管理,例如支持合并cell、将cell按照分数分割等功能。使用gridspec完成子图布局时,我们需要先创建一个GridSpec对象,然后根据需要指定行数、列数、高度比例和宽度比例等参数,最后使用subplots_from_gridspec函数生成图像。例如,以下代码用gridspec实现了一个带有三个子图和一些文本注释的复杂布局。
```
import matplotlib.gridspec as gs
import matplotlib.pyplot as plt
import numpy as np
# 创建一个4x4的GridSpec对象,并设置每个子图在网格中的位置和大小
grid = gs.GridSpec(nrows=4, ncols=4, height_ratios=[1, 1, 1, 1], width_ratios=[1, 1, 1, 1])
sub1 = grid[0:2, 0:2]
sub2 = grid[0:2, 2:4]
sub3 = grid[2:3, 0:2]
sub4 = grid[2:3, 2:4]
sub5 = grid[3:, :]
# 创建画布和各子图
fig = plt.figure()
ax1 = fig.add_subplot(sub1)
ax2 = fig.add_subplot(sub2)
ax3 = fig.add_subplot(sub3)
ax4 = fig.add_subplot(sub4)
ax5 = fig.add_subplot(sub5)
# 绘制各子图
x = np.linspace(-np.pi, np.pi, 100)
ax1.plot(x, np.sin(x), color="red", linewidth=1.0)
ax2.plot(x, np.cos(x), color="green", linewidth=1.0)
ax3.scatter(x, np.sin(x), color="blue", linewidth=1.0, s=5)
ax4.bar(x, np.cos(x), color="purple", width=0.1)
ax5.text(0.5, 0.5, "This is an annotation", horizontalalignment="center", fontsize=16)
# 设置各子图的标题和标签
ax1.set_title("Sine Wave")
ax2.set_title("Cosine Wave")
ax3.set_title("Scatter Plot")
ax4.set_title("Bar Chart")
ax1.set_xlabel("X")
ax2.set_xlabel("X")
ax3.set_xlabel("X")
ax4.set_xlabel("X")
ax1.set_ylabel("Sine(X)")
ax2.set_ylabel("Cosine(X)")
ax3.set_ylabel("Y")
ax4.set_ylabel("Y")
# 显示图像
plt.show()
```
以上就是使用subplot在matplotlib中绘制多个子图的基本和高级用法。当然除了这些用法之外,还有很多其他绘图技巧和工具可以用于数据可视化。在掌握了这些使用技巧之后,我们可以更加高效地进行数据分析和可视化,使得我们能够更加深入地理解数据背后的规律,并为进一步的数据挖掘和研究打下更加坚实的基础。