如何在sharex=True时设置子图间差异化垂直间距(顶中留距、中底无距)
实现思路与代码方案
核心思路
由于plt.subplots的hspace参数是全局控制所有子图垂直间距的,无法单独指定某两个子图的间距,因此需要通过手动控制子图布局的方式实现差异化间距:
- 让中间与底部子图完全贴合(间距为0)
- 顶部与中间子图保留指定垂直间距
- 同时确保三个子图共享x轴
方案一:使用GridSpec子网格(推荐)
通过GridSpec创建主网格,再将中间和底部子图放入一个子网格并设置其内部间距为0,主网格控制顶部与子网格的间距,同时实现x轴共享。
import numpy as np import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec ii = np.arange(100) fig = plt.figure(figsize=(8, 6)) # 创建主网格:3行1列,设置高度比例 main_gs = GridSpec(3, 1, height_ratios=[1, 2, 3]) # 设置主网格的垂直间距(控制顶部与中间子图的间距) main_gs.update(hspace=0.3) # 顶部子图 ax_top = fig.add_subplot(main_gs[0]) # 为中间和底部子图创建子网格,内部间距设为0 mid_bottom_gs = main_gs[1:3].subgridspec(2, 1, hspace=0) ax_mid = fig.add_subplot(mid_bottom_gs[0], sharex=ax_top) ax_bottom = fig.add_subplot(mid_bottom_gs[1], sharex=ax_top) # 隐藏顶部和中间子图的x轴刻度(因为共享x轴,只保留底部刻度) plt.setp(ax_top.get_xticklabels(), visible=False) plt.setp(ax_mid.get_xticklabels(), visible=False) # 绘图 ax_top.plot(ii) ax_mid.plot(ii + 2) ax_bottom.plot(ii * 2) plt.show()
方案二:手动调整子图位置
先通过plt.subplots创建共享x轴的子图,再获取每个子图的位置参数,手动修改中间与底部子图的位置使其贴合,同时拉开顶部与中间子图的间距。
import numpy as np import matplotlib.pyplot as plt ii = np.arange(100) # 创建共享x轴的3个子图 fig, axs = plt.subplots(nrows=3, sharex=True, height_ratios=[1, 2, 3], figsize=(8, 6)) # 获取每个子图的当前位置(返回值为[左, 下, 宽, 高]) pos_top = axs[0].get_position() pos_mid = axs[1].get_position() pos_bottom = axs[2].get_position() # 调整中间子图的位置,使其底部与底部子图的顶部重合(间距为0) new_pos_mid = [pos_mid.x0, pos_bottom.y1, pos_mid.width, pos_mid.height] axs[1].set_position(new_pos_mid) # 调整顶部子图的位置,与中间子图顶部留出指定间距(这里用0.05作为间距值,可按需调整) new_pos_top = [pos_top.x0, new_pos_mid[1] + new_pos_mid[3] + 0.05, pos_top.width, pos_top.height] axs[0].set_position(new_pos_top) # 绘图 axs[0].plot(ii) axs[1].plot(ii + 2) axs[2].plot(ii * 2) plt.show()
关键说明
- 两种方案都确保了
sharex=True的要求,通过sharex参数或手动指定共享轴实现 - 方案一的优势是布局更灵活、自适应图形大小,无需手动调整像素级位置
- 方案二更直观,适合快速调整已有代码的场景
内容的提问来源于stack exchange,提问作者Marti
相关产品推荐
相关产品推荐

