如何创建左列1图、右列3图的子图布局?兼GridSpec详解
问题与解决方案
问题描述
想要创建2列子图布局:第一列仅放置1个图,第二列放置3个图。尝试两种方法后遇到问题:
- 使用
plt.subplot无法添加第4个图,且无法控制子图尺寸比例; - 使用
GridSpec实现了基础布局,但不会自定义子图尺寸。
用户尝试的代码如下:
方法1:plt.subplot 实现(未完成)
import matplotlib.pyplot as plt def format_axes(fig): for i, ax in enumerate(fig.axes): ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") ax.tick_params(labelbottom=False, labelleft=False) fig = plt.figure() ax1 = plt.subplot(222) ax2 = plt.subplot(224) ax3 = plt.subplot(121) axes = [ax1, ax2, ax3] format_axes(fig) plt.tight_layout() plt.show()
方法2:GridSpec 实现(未控制尺寸)
import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec def format_axes(fig): for i, ax in enumerate(fig.axes): ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") ax.tick_params(labelbottom=False, labelleft=False) fig = plt.figure(layout="constrained") gs = GridSpec(3, 2, figure=fig) ax1 = fig.add_subplot(gs[: , 0]) ax2 = fig.add_subplot(gs[0, -1]) ax3 = fig.add_subplot(gs[1, 1]) ax4 = fig.add_subplot(gs[-1, 1]) format_axes(fig) plt.show()
解决方案
1. 实现目标布局并控制尺寸
要自定义子图的列宽、行高,只需在创建GridSpec时添加width_ratios(列宽比例)或height_ratios(行高比例)参数。以下是完整可运行代码:
import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec def format_axes(fig): for i, ax in enumerate(fig.axes): ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") ax.tick_params(labelbottom=False, labelleft=False) fig = plt.figure(layout="constrained") # 定义3行2列网格,设置列宽比例为2:1,行高比例为1:1:1(可自由调整) gs = GridSpec(3, 2, figure=fig, width_ratios=[2, 1], height_ratios=[1, 1, 1]) ax1 = fig.add_subplot(gs[:, 0]) # 第一列跨所有3行 ax2 = fig.add_subplot(gs[0, 1]) # 第二列第1行 ax3 = fig.add_subplot(gs[1, 1]) # 第二列第2行 ax4 = fig.add_subplot(gs[2, 1]) # 第二列第3行 format_axes(fig) plt.show()
width_ratios=[2,1]:表示第一列宽度是第二列的2倍,可根据需求修改为任意正数比例(比如[3,2]);height_ratios=[1,1,1]:表示第二列的三个子图高度均分,若想让某一个子图更高,可改为[2,1,1]这类比例。
2. GridSpec 核心用法讲解
GridSpec是Matplotlib用于灵活布局子图的工具,核心逻辑是先定义网格框架,再将子图映射到网格的指定区域:
(1)创建GridSpec对象
gs = GridSpec(nrows, ncols, figure=fig, width_ratios=[...], height_ratios=[...])
nrows/ncols:网格的总行数、总列数;width_ratios:可选参数,列表类型,每个元素对应一列的宽度比例,默认所有列宽度均分;height_ratios:可选参数,列表类型,每个元素对应一行的高度比例,默认所有行高度均分。
(2)映射子图到网格区域
使用fig.add_subplot(gs[行范围, 列范围]),支持Python切片语法:
gs[:, 0]:选中所有行(:表示全部)、第0列,即跨所有行的单列区域;gs[0, 1]:选中第0行、第1列的单个网格单元;gs[1:3, 1]:选中第1到第2行(左闭右开规则)、第1列的区域;gs[-1, :]:选中最后一行、所有列的区域。
这种方式完全支持任意nrows×ncols的网格布局,通过切片和比例参数就能实现各种复杂的子图排列和尺寸控制。
内容的提问来源于stack exchange,提问作者bored af
相关产品推荐
相关产品推荐

