Matplotlib基础(6):多张图的布局及定制subplots/gridspec/mosaic

作图时首先就要确定图片内容的布局,此处小结一下多图布局的常规操作。绘制草图及常用的图使用==subplots==进行布局即可,涉及更多元化的布局可以使用==gridspec==以及最新的==subplot_mosaic==

布局示意

这里主要记录的是多个==axes==(图形)在一张或多种画布==figure==中的布局。

新建画布的步骤可以拆成两步,也可以合并为一行代码

  1. 先新建一个figure(然后往其中继续添加subfigures)
  2. 往figiue上添加axes,即添加图形
1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
matplotlib.rcParams['figure.dpi'] = 120

fig,ax_array = plt.subplots(
nrows = 2, ncols = 2,
figsize=(5,5),
layout='constrained')
# 等效于
fig = plt.figure(figsize=(5,5),layout='constrained')
ax_array = fig.subplots(nrows = 2, ncols = 2)

固定行列subplots

创建指定行列数默认等大小的若干图形,参数:

  • nrows,ncols,行列数
  • figsize=() #单位是英寸,如果设置为A4纸大小为(21/2.54,29.7/2.54)
  • layout,布局,默认紧凑'constrained', 'compressed', 'tight'
    • set_constrained_layout: w_pad, h_pad,调节ax周边包围的大小,单位是英寸
  • sharex=‘col’, sharey=‘row’
  • gridspec_kw(此参数也适用于subfigure,调整画布之间的比例等):
    • wspace, hspace 调整行列之间的间隙
    • height_ratios, width_ratios:调整行列图形的大小比例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
fig,ax_array = plt.subplots(
nrows = 2, ncols = 2,figsize=(6,4),
layout='constrained')

ax_array[0, 0].bar(["a", "b", "c"], [5, 7, 9])
ax_array[0, 1].plot([1, 2, 3])
ax_array[1, 0].hist(hist_data, bins="auto")
ax_array[1, 1].imshow([[1, 2], [2, 1]])
# 以下等价
# axes = ax_array.flatten()
# axes[0].bar(["a", "b", "c"], [5, 7, 9])
# axes[1].plot([1, 2, 3])
# axes[2].hist(hist_data, bins="auto")
# axes[3].imshow([[1, 2], [2, 1]])

其他参数示例:

1
2
3
4
5
6
# 左图
fig,ax_array = plt.subplots(2,2, sharex='col',sharey='row',
gridspec_kw={'hspace': 0,
'wspace': 0})
# 右图
fig,ax_array = .subplots(2,2,gridspec_kw={'height_ratios': [1,2],'width_ratios':[1,3]})

格网布局gridspec

将平面划分为若干行列的网格,然后选取若干“网格填色”组成预期的布局

用法示例

添加的步骤代码:

  1. 创建Figure:fig = plt.figure()
  2. 创建并添加格网:grids = fig.add_gridspec(ncols=2, nrows=3)
  3. 选取格网创建ax:ax = fig.add_subplot(grids[0, :])

添加2*3的格网,然后合并为四个,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 对应左图
fig = plt.figure(figsize=(5, 5), layout="constrained")
grids = fig.add_gridspec(ncols=2, nrows=3)
ax0 = fig.add_subplot(grids[0, :])
ax10 = fig.add_subplot(grids[1, 0])
ax11 = fig.add_subplot(grids[1, 1])
ax2 = fig.add_subplot(grids[2, :])
# 对应右图
fig = plt.figure(figsize=(5, 5), layout="constrained")
grids = fig.add_gridspec(ncols=2, nrows=3)
ax0 = fig.add_subplot(grids[0, :])
ax10 = fig.add_subplot(grids[1:, 0])
ax11 = fig.add_subplot(grids[1, 1])
ax2 = fig.add_subplot(grids[2, 1])

嵌套格网subgridspec或者多subfigures

嵌套的格网实现分块的布局结构,示例如下:

  1. 创建格网/分块 plt.figure(), fig.add_gridspec()
  2. 每个格网分别进行二次划分grids0[0].subgridspec()
1
2
3
4
5
6
7
8
9
10
11
12
13
fig = plt.figure(figsize=(7, 4),layout="constrained")
gs0 = fig.add_gridspec(nrows=1, ncols=2)#一行两列,两个格网
gs00 = gs0[0].subgridspec(2, 2)# 左侧两行两列的四个格网
gs01 = gs0[1].subgridspec(3, 1)# 三行一列的三个格网

ax1 = fig.add_subplot(gs00[0,0])
ax2 = fig.add_subplot(gs00[0,1])
ax3 = fig.add_subplot(gs00[1,0])
ax4 = fig.add_subplot(gs00[1,1])

ax5 = fig.add_subplot(gs01[0])
ax6 = fig.add_subplot(gs01[1])
ax7 = fig.add_subplot(gs01[2])

有时候左右两块想单独设置各自的布局及其他参数,则可以拆成两个Figure

1
2
3
4
5
6
7
8
9
10
11
fig = plt.figure(figsize=(7, 4),layout="constrained",facecolor='w')
subfigs = fig.subfigures(nrows=1, ncols=2)

axs0 = subfigs[0].subplots(2, 2) #左侧figure创建subplots
axs1 = subfigs[1].subplots(3, 1)

# 添加其他信息示意
subfigs[0].suptitle('subfigs[0]\nLeft side',color='b',fontsize=12)
subfigs[0].supxlabel('xlabel for subfigs[0]')
subfigs[1].suptitle(r'supertitle subfigs[1]',color='b',fontsize=12)
subfigs[1].supylabel('ylabel for subfigs[1]')

形象化格网布局mosaic

到了上面这些基本能够通过设计实现自己想要的任意布局,最新的版本还提供了更为便捷的绘图接口fig.subplot_mosaic(),可以通过字典、字符串、numpy数组表示的方式得到目标的格网布局

举例,表达方式多种多样,使用字符串即可,更多案例可以参考官方

  • 获取ax的方式则变成了字典,如ax0 = ax_dict[‘A’],ax0 = ax_dict[‘1’]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
mosaic ="AB;CD"
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
# 以下等价
mosaic ="12;34"
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
# 以下等价
fig = plt.figure(constrained_layout=True)
axd = fig.subplot_mosaic(
"""
AB
CD
""")

更加丰富的表达:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 图1
fig = plt.figure(constrained_layout=True)
axd = fig.subplot_mosaic("ABD;CCD")
# 图2
fig = plt.figure(constrained_layout=True)
axd = fig.subplot_mosaic("A.C;BBB;.D.")
# 图3
fig = plt.figure(constrained_layout=True)
axd = fig.subplot_mosaic(".a.;bAc;.d.",
gridspec_kw={"height_ratios":[1, 3.5, 1],
"width_ratios":[1, 3.5, 1]}
# set the height ratios between the rows
# set the width ratios between the columns
)
# 图4,嵌套列表
inner = [
["inner A"],
["inner B"],
]

outer_nested_mosaic = [
["main", inner],
["bottom", "bottom"],
]
fig = plt.figure(constrained_layout=True)
axd = fig.subplot_mosaic(
outer_nested_mosaic, empty_sentinel=None
)

参考

  1. https://matplotlib.org/devdocs/tutorials/index.html
  2. https://matplotlib.org/devdocs/api/index.html
  3. https://matplotlib.org/devdocs/gallery/index.html