Matplotlib——绘制多个子图(Axes)及其布局

  • Post author:
  • Post category:其他


本文介绍如何用matplotlib绘制多个子图,并介绍控制它们布局的方法。按照其布局方式,分为均一排布,规整排布和跨行列排布三种。



一.均一排布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个小标题)

在这里插入图片描述


返回值

:plt.subplots()返回 类似的 [ [figure], [axes1, axes2…] ]类似的东西,需要用两个变量解包接受。读者可以自行打印返回结果验证一下。

从返回值的类型我们需要知道

:plt.subplots()不仅创建了figure,把布局规划好,且且为我们在每个子图框中创建了axes。关于解包,请参考这篇博客:

https://editor.csdn.net/md/?articleId=111387910



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.示例

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()

运行结果为:
在这里插入图片描述



二.规整排布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行五列的子图框。


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列的子图框。

见代码:

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()

运行结果如下:
在这里插入图片描述



三.跨行列子图布局

跨行列子图的figure划分方法一样,都是调用

fig.add_gridspec()

。想要实现跨行列的布局,在选中子图框时切片即可。例如:spec[:1,1:2]时选中第一二行的二三列。见示例:

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()

选中了第一二行和二三列(共三行五列),运行结果如下:

在这里插入图片描述

参考:

https://nbviewer.jupyter.org/github/datawhalechina/fantastic-matplotlib/blob/main/%E7%AC%AC%E4%B8%89%E5%9B%9E%EF%BC%9A%E5%B8%83%E5%B1%80%E6%A0%BC%E5%BC%8F%E5%AE%9A%E6%96%B9%E5%9C%86.ipynb#1.-%E5%A2%A8%E5%B0%94%E6%9C%AC1981%E5%B9%B4%E8%87%B31990%E5%B9%B4%E7%9A%84%E6%AF%8F%E6%9C%88%E6%B8%A9%E5%BA%A6%E6%83%85%E5%86%B5



版权声明:本文为qq_46110834原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。