无法播放?请 点击这里 跳转到Youtube
切换视频源:

上一章我们学习了图例和标注相关的内容,本章来学习一下如何在同一个窗口中画多个小图。先导入本章需要的库:

import matplotlib.pyplot as plt
import numpy as np

子图 Subplot

首先我们来学习如何使用subplot在一个窗口中画多个图片。subplot函数需要三个参数来定位图片,第一个和第二个参数代表将窗口分成几行几列,第三个参数指定接下来要画的图片位置。

plt.figure(figsize=(8, 5))
plt.subplot(2, 3, 2) # 将窗口分为2行3列,当前位置为2
plt.plot([0, 10], [0, 10])
plt.title("2,3,2")
plt.subplot(2, 3, 4) # 将窗口分为2行3列,在第4个位置画图
plt.plot([0, 10], [0, 10])
plt.title("2,3,4")
plt.subplot(2, 3, 5)
plt.plot([0, 10], [0, 10])
plt.title("2,3,5")
plt.tight_layout() # 紧凑图像
plt.show()

使用subplots画图的第二种方法就是通过返回的对象进行操作:使用subplots定义好窗口被分割的方式之后,拿到第二个返回值axe,并通过axe的索引值来操作子图:

fig, axe = plt.subplots(nrows = 2, ncols = 2)
axe[0][1].plot([0, 10], [0, 10]) # [0][1]代表第一行第二列
plt.show()

如果subplots只有一个维度,axe可以当做list来使用:

fig, axe = plt.subplots(nrows = 2, ncols = 1) # 窗口被分成两行一列
axe[1].plot([0, 10], [0, 10])
plt.show()

以下这个例子能帮助你更好地理解子图相对应的位置:

fig, axe = plt.subplots(nrows=2, ncols=2, figsize=(10, 5))
plt.tight_layout()
axe[0][0].set_title("1st subplot") # 第一行第一列
axe[1][0].plot([0,10], [0, 10]) # 第二行第一列
axe[1][1].set_title("4th subplot") # 第二行第二列
plt.tight_layout() # 紧凑图像
plt.show()

如果我们需要展示不同大小的子图,比如把俩个小图放到第一行,而单独一个大图放在第二行呢。

如要实现则需要定义不同的子图分割方式(第一个和第二个参数),如下第二行的子图能直接占据了一整行:

plt.subplot(2, 2, 1) # 将窗口分为2行2列,接下来画第一个位置的子图
plt.title("2,2,1")
plt.plot([0, 10], [0, 10])

plt.subplot(2, 2, 2) 
plt.plot([0, 10], [0, 10])
plt.title("2,2,3")

plt.subplot(2, 1, 2) # 将窗口分为2行1列,接下来画第二个位置的子图,会将第二行填满
plt.plot([0, 10], [0, 10])
plt.title("2,1,2")

plt.tight_layout() # 紧凑图像
plt.show()

分格显示 GridSpec 自定义子图

接下来学习另一种更灵活组合子图的方法,就是使用GridSpec:

from matplotlib.gridspec import GridSpec

GridSpec可以更灵活地定义子图的排列,让子图的大小各不相同,从而对子图进行更复杂的操作:

fig = plt.figure(dpi=100) # 表示图片的像素(the resolution in dots per inch),值越大图像越清晰
gs = GridSpec(2, 2, width_ratios=[1, 2], height_ratios=[3, 1]) # width_ratios定义了列宽度的相对比例,height_ratios定义了行高度的相对比例

ax1 = fig.add_subplot(gs[0])
ax1.text(0.5,0.5,"1st plot",verticalalignment='center', ha='center') # 垂直对称和水平对称都设为中间
ax1.plot([0,1], [0, 1])
ax2 = fig.add_subplot(gs[1])
ax2.text(0.5,0.5,"2nd plot",verticalalignment='center', ha='center')
ax3 = fig.add_subplot(gs[2])
ax3.text(0.5,0.5,"3rd plot",verticalalignment='center', ha='center')
ax4 = fig.add_subplot(gs[3])
ax4.text(0.5,0.5,"4th plot",verticalalignment='center', ha='center')
plt.show()

如果想要让一个子图占据整行或整列,可以在相对应维度使用冒号(:)进行索引,比如使用gs[0, :],则代表占据第一行的所有列:

fig = plt.figure(dpi=100)
gs = GridSpec(2, 2, width_ratios=[1, 3], height_ratios=[5, 1]) 

ax1 = fig.add_subplot(gs[0, :]) # 占据第一行的所有列
ax1.text(0.5, 0.5, "1st plot", verticalalignment='center', ha='center') 
ax2 = fig.add_subplot(gs[1, 1])
ax2.text(0.5, 0.5, "2nd plot", verticalalignment='center', ha='center')
ax3 = fig.add_subplot(gs[1, 0])
ax3.text(0.5, 0.5, "3rd plot", verticalalignment='center', ha='center')
plt.show()

如果使用gs[:, 1],则代表占据所有行的第二列:

fig = plt.figure(dpi=100)
gs = GridSpec(2, 2, width_ratios=[1, 3], height_ratios=[5, 1])

ax1 = fig.add_subplot(gs[0, 0])
ax1.text(0.5, 0.5, "1st plot", verticalalignment='center', ha='center')
ax2 = fig.add_subplot(gs[:, 1]) # 占据所有行的第二列
ax2.text(0.5, 0.5, "2nd plot", verticalalignment='center', ha='center')
ax3 = fig.add_subplot(gs[1, 0])
ax3.text(0.5, 0.5, "3rd plot", verticalalignment='center', ha='center')
plt.show()

图中图

最后我们来学习一下如何在一个图片中画另一个小图,首先创建好用来画图的数据:

x = np.linspace(-3, 3, 100)
y = np.sin(x)

首先使用正常的方式画好图之后,直接使用add_axes,传入4个定义图中图的参数,就能在原来的图上加入小图了:

fig, ax1 = plt.subplots()
ax1.plot(x, y, 'orange')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('Big 1')

left, bottom, width, height = 0.25, 0.6, 0.2, 0.2 # 四个值都代表占据整个窗口的百分比
ax2 = fig.add_axes([left, bottom, width, height]) # [离左边的位置,离底部的位置,宽度,高度]
y2 = - x ** 2
ax2.plot(x, y2, 'g')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('small 1')

plt.show()

我们再为右下角加上一张小图:

fig, ax1 = plt.subplots()
ax1.plot(x, y, 'orange')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('Big 1')

left, bottom, width, height = 0.25, 0.6, 0.2, 0.2
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(x, y2, 'g')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('small 1')

plt.axes([0.65, 0.2, 0.2, 0.25]) # 四个值都代表占据整个窗口的百分比
plt.plot(x, x ** 2, 'r')
plt.xlabel('x')
plt.ylabel('y')
plt.title('small 2')
plt.show()

以上就是和子图相关的内容啦,掌握这些内容后,你就能在同一个窗口中组合多个子图,从而传递更多的信息。