# Matplotlib——绘制多个子图(Axes)及其布局 ## 一.均一排布plt.subplots() 均一排布的含义:所有子图的大小相同,规整的按行列排布在画布上。 **强调**:subplots()是plt类下属的方法。 ### 1.subplots()控制布局 subplot函数及其重要参数:`plt.subplots(row_number, column_number, figsize=(width, height), sharex=True, sharey=True)` `row_number, column_number`:一共生成多少行,多少列的子图(axes)。 `figsize=(width, height)`:指定整个画布的大小。 这两个参数综合起来理解就是:创建一个大小为figsize的画布,并把画布按row_number, column_number划分成均一的子图框格,框格里可以添加子图(axes)。 `sharex=True , sharey=True` :是否共享横轴和纵轴刻度。 下图是一个共享x轴刻度,但是不共享y轴刻度是示例。前两行的x轴刻度因为相同,所以隐藏了。(x轴,y轴刻度的设置见第3个小标题) ![1701618555416](image/matplotlib_subplot/1701618555416.png) 返回值:`plt.subplots()`返回 `[[figure], [axes1, axes2…]]`类似的东西,需要用两个变量解包接受。读者可以自行打印返回结果验证一下。从返回值的类型我们需要知道:`plt.subplots()`不仅创建了figure,把布局规划好,且为我们在每个子图框中创建了axes。 ### 2.suptitle() 添加画布的标题 `fig.suptitle('引号里添加标题', size=number)` ### 3.用axes类及其方法绘制子图 选定一个子图框:若axs为创建的axes变量名,使用 `axs[i][j]`选中第 `i+1`行 `j+1`列的子图框。 绘图方法:axes类定义了和plt类似的绘图方法:`.plot`, `.hist()`, `.scatter()`, `.bar()`, `barh.()`, `pie.()`等,直接使用即可。 子图标题,坐标头与坐标轴范围: 1. 标题:axs[0][0].set_titile(‘引号里输入子图标题’) 2. 坐标头:axs[0][0].set_xlabel(‘横坐标头’) , axs[0][0].set_ylable(‘纵坐标头’) 3. 坐标轴范围:axs[0][0].set_xlim(min,max) , axs[0][0].set_ylim(min,max) ### 4.示例 ```python import matplotlib.pyplot as plt import numpy as np #把画布分为三行五列,并设置figure标题 fig,axs=plt.subplots(3,3,figsize=(15,15),sharex=True,sharey=False) fig.suptitle('use .suptitle() to add a figure title') #选中第三行第三个画出散点图 axs[2][2].scatter(np.random.randn(10),np.random.randn(10)) axs[2][2].set_title('scatter') axs[2][2].set_xlabel('x label') axs[2][2].set_ylabel('y label') axs[2][2].set_xlim(-5,8) #用for循环在第一二行的所有子图框中作图 for i in range(2): for j in range(3): axs[i][j].plot([2,4,8],range(3)) plt.show() ``` 运行结果为: ![1701618622365](image/matplotlib_subplot/1701618622365.png) ## 二.规整排布add_gridspec 所谓规整排布,是笔者自己的叫法,意思是所有子图按行列排布,没有出现跨行或跨列的情况,但是大小不一样。 强调:`add_gridspec()`是figure类下属的方法。所以我们需要先用`plt.figure()`创建一个figure。 ### 1.add_gridspec()重要参数 `spec = fig.add_gridspec(nrows=number, ncols=5, width_ratios=[1,2,3,4,5], height_ratios=[1,3])` * `nrows=2, ncols=5 `: 与 `subplots()`类似,把figure分成2行5列的子图框。 * `width_ratios=[1,2,3,4,5]` :宽度比例。列表里的元素数应当与列数相同,代表各列的宽度比例。例如,ncols=5,那么list中应当有5个元素。 * `height_ratios=[1,3])`:高度比例。列表里的元素数应当与行数相等,代表各行的高度比例。例如nrows=2,那么列表里应该有两个元素。 * 返回值:建议理解为无返回值。`fig.add_gridspec()`只是为figure划分了布局,并没有为我们创建axes,所以我们需要自己在子图框中创建axes。 ### 2.绘制规整排布的子图 `fig.add_gridspec()`为我们把figure按行列划分成了子图框,所以我们可以用行列号选中子图框。假设我们用spec变量接受了fig.add_gridspec()的结果,那么我们可以用`spec[i][i]`来选中第i+1行j+1列的子图框。(注意与plt.subplots()比较,均一图选中的是axes,而规整图仅仅选中了子图框)。 为了绘制子图,我们需要使用fig.add_subplot()方法,并使用spec[i][i]作为参数选中第i+1行j+1列的子图框。 见代码: ```python import matplotlib.pyplot as plt import numpy as np fig=plt.figure(figsize=(14,7)) spec=fig.add_gridspec(nrows=2,ncols=5,width_ratios=[1,5,3,2,3],height_ratios=[1,3]) #在第二行第五列的子图框绘制子图 ax=fig.add_subplot(spec[1,4]) ax.scatter(np.random.rand(15),np.random.rand(15)) #用for循环为前三列绘制子图 for i in range(2): for j in range(3): ax=fig.add_subplot(spec[i,j]) ax.plot(range(5),[7,9,10,12,15]) plt.show() ``` 运行结果如下: ![1701618674552](image/matplotlib_subplot/1701618674552.png) ## 三.跨行列子图布局 跨行列子图的figure划分方法一样,都是调用 `fig.add_gridspec()`。想要实现跨行列的布局,在选中子图框时切片即可。例如:`spec[:1,1:2]`时选中第一二行的二三列。见示例: ```python import matplotlib.pyplot as plt import numpy as np fig=plt.figure(figsize=(14,7)) spec=fig.add_gridspec(nrows=3,ncols=5,width_ratios=[1,5,3,2,3],height_ratios=[1,3,2]) #绘制跨行列的子图,把一二行的二三列连成一块 ax=fig.add_subplot(spec[:2,1:3]) #选中了一二行和二三列 ax.scatter(np.random.rand(15),np.random.rand(15)) plt.show() ``` 选中了第一二行和二三列(共三行五列),运行结果如下: ![1701618734754](image/matplotlib_subplot/1701618734754.png)