一、多图绘制入口:subplot 与 subplots
Matplotlib 的 pyplot 提供 subplot() 和 subplots() 两种多子图绘制方式。前者在绘图时需要指定子图位置,每调用一次通常只处理一个子图;后者可以一次生成多个子图,调用时直接使用返回对象中的 ax 即可。
二、subplot:按行列位置逐个添加子图
subplot 常见调用形式包括:- subplot(nrows, ncols, index, **kwargs)
- subplot(pos, **kwargs)
- subplot(**kwargs)
- subplot(ax)
复制代码 它会把整个绘图区域分成 nrows 行、ncols 列,然后按从左到右、从上到下的顺序给每个子区域编号为 1...N。左上角子区域编号为 1,右下角编号为 N,具体使用哪个子区域由 index 决定。
当 nrows=1、ncols=2 时,图表被划分为 1x2 区域,对应坐标是 (1,1)、(1,2)。index=1 表示第一行第一列,index=2 表示第一行第二列。示例代码:- import matplotlib.pyplot as plt
- import numpy as np
- #plot 1:
- xpoints = np.array([0, 6])
- ypoints = np.array([0, 100])
- plt.subplot(1, 2, 1)
- plt.plot(xpoints,ypoints)
- plt.title("plot 1")
- #plot 2:
- x = np.array([1, 2, 3, 4])
- y = np.array([1, 4, 9, 16])
- plt.subplot(1, 2, 2)
- plt.plot(x,y)
- plt.title("plot 2")
- plt.suptitle("W3Cschool subplot Test")
- plt.show()
复制代码 当 nrows=2、ncols=2 时,区域被划分为 2x2,对应坐标是 (1,1)、(1,2)、(2,1)、(2,2)。index 依次为:1 对应 (1,1),2 对应 (1,2),3 对应 (2,1),4 对应 (2,2)。代码示例:- import matplotlib.pyplot as plt
- import numpy as np
- #plot 1:
- x = np.array([0, 6])
- y = np.array([0, 100])
- plt.subplot(2, 2, 1)
- plt.plot(x,y)
- plt.title("plot 1")
- #plot 2:
- x = np.array([1, 2, 3, 4])
- y = np.array([1, 4, 9, 16])
- plt.subplot(2, 2, 2)
- plt.plot(x,y)
- plt.title("plot 2")
- #plot 3:
- x = np.array([1, 2, 3, 4])
- y = np.array([3, 5, 7, 9])
- plt.subplot(2, 2, 3)
- plt.plot(x,y)
- plt.title("plot 3")
- #plot 4:
- x = np.array([1, 2, 3, 4])
- y = np.array([4, 5, 6, 7])
- plt.subplot(2, 2, 4)
- plt.plot(x,y)
- plt.title("plot 4")
- plt.suptitle("W3Cschool subplot Test")
- plt.show()
复制代码
三、subplots:一次创建画布和多个 Axes
subplots() 的语法格式为:- matplotlib.pyplot.subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
复制代码 关键参数含义如下:
- nrows:默认 1,设置图表行数。
- ncols:默认 1,设置图表列数。
- sharex、sharey:设置 x、y 轴是否共享属性,默认 false,可设为 'none'、'all'、'row' 或 'col'。False 或 none 表示每个子图的 x 轴或 y 轴独立;True 或 'all' 表示所有子图共享 x 轴或 y 轴;'row' 表示每个子图行共享一个 x 轴或 y 轴;'col' 表示每个子图列共享一个 x 轴或 y 轴。
- squeeze:布尔值,默认 True,表示额外维度从返回的 Axes 对象中挤出。对于 N*1 或 1*N 个子图,返回一维数组;对于 N*M,且 N>1、M>1,返回二维数组。如果设为 False,则不进行挤压操作,返回元素为 Axes 实例的二维数组,即使最终是 1x1。
- subplot_kw:可选字典,把关键字传递给 add_subplot() 来创建每个子图。
- gridspec_kw:可选字典,把关键字传递给 GridSpec 构造函数,用于创建放在网格里的子图。
- **fig_kw:把详细关键字参数传给 figure() 函数。
实践中,subplots 返回的 fig 代表画布,ax 或 axs 代表一个或多个 Axes。示例代码:- import matplotlib.pyplot as plt
- import numpy as np
- # 创建一些测试数据 -- 图1
- x = np.linspace(0, 2*np.pi, 400)
- y = np.sin(x**2)
- # 创建一个画像和子图 -- 图2
- fig, ax = plt.subplots()
- ax.plot(x, y)
- ax.set_title('Simple plot')
- # 创建两个子图 -- 图3
- f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
- ax1.plot(x, y)
- ax1.set_title('Sharing Y axis')
- ax2.scatter(x, y)
- # 创建四个子图 -- 图4
- fig, axs = plt.subplots(2, 2, subplot_kw=dict(projection="polar"))
- axs[0, 0].plot(x, y)
- axs[1, 1].scatter(x, y)
- # 共享 x 轴
- plt.subplots(2, 2, sharex='col')
- # 共享 y 轴
- plt.subplots(2, 2, sharey='row')
- # 共享 x 轴和 y 轴
- plt.subplots(2, 2, sharex='all', sharey='all')
- # 这个也是共享 x 轴和 y 轴
- plt.subplots(2, 2, sharex=True, sharey=True)
- # 创建标识为 10 的图,已经存在的则删除
- fig, ax = plt.subplots(num=10, clear=True)
- plt.show()
复制代码
四、参数选择与适用场景
从调用方式看,subplot 更适合按位置逐个添加子图:每次调用传入行数、列数和 index,随后用 plt.plot、plt.title 等当前轴方法绘图。subplots 更适合一次性搭好画布和子图数组,再通过 ax 对象分别绘图,尤其在需要共享轴、统一设置 subplot_kw 或 gridspec_kw 时更直接。
需要特别注意 squeeze 对返回结构的影响:1x2 这类布局在默认 squeeze=True 时可直接解包成两个 Axes;2x2 这类行列都大于 1 的布局返回二维数组,需要用 axs[0,0]、axs[1,1] 等方式访问。若希望无论行列数如何都得到二维数组,可把 squeeze=False。共享轴方面,sharex/sharey 的 False、none、True、all、row、col 分别对应独立、全部共享、按行共享和按列共享,实际选择应结合坐标刻度可读性与子图布局决定。
总结来说,subplot 与 subplots 都是 Matplotlib 绘制多图的常用入口,核心差异在于定位方式、返回对象和参数传递方式。逐个定位子图时用 subplot,批量创建并统一管理 Axes 时用 subplots,理解了行列编号、index、sharex/sharey、squeeze 等参数后,多子图代码会更容易维护。 |