Python Matplotlib为3×3布局所有子图添加断轴效果的实现方法
3×3布局子图批量添加断轴效果实现
原代码无法正常运行主要是几个核心问题:
- 循环索引逻辑错误:三层嵌套循环里
j没有递增规则,xx[j]取值会出错 - 存在语法错误:均值计算语句多了冗余括号,且均值计算后的数组维度和x轴序列不匹配,无法直接绘图
- 断轴视觉标识缺失:仅隐藏了上下边框,没有添加断轴斜切标记,无法识别断轴效果
- 共享轴配置冲突:初始化子图时开启全局
sharex/sharey,后续新增的断轴没有同步配置,会出现刻度错位、重复显示 - 刻度未做隐藏处理:上方断轴的x轴刻度、标签没有隐藏,会和下方轴的刻度重叠
可直接运行的实现代码
下面的代码用模拟数据演示效果,你替换成自己的some_data和业务逻辑即可:
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable # -------------------------- 替换成你自己的数据 -------------------------- # 模拟数据维度对齐原代码的[op, pl, 时间序列]索引逻辑 some_data = np.concatenate([ np.random.randint(0, 25, size=(3,3,13)), # 低数值区间数据 np.random.randint(50, 65, size=(3,3,13)) # 高数值区间数据 ], axis=2) xx = np.arange(13) # ----------------------------------------------------------------------- fig, ax = plt.subplots(nrows=3, ncols=3, figsize=(17, 12), facecolor='white') fig.subplots_adjust(hspace=0.3, wspace=0.25) # 断轴斜切标记参数 slash_len = 0.015 slash_kwargs = dict(color='k', clip_on=False) for pl in range(3): for op in range(3): # 为当前子图创建上方断轴 divider = make_axes_locatable(ax[pl, op]) ax_top = divider.new_vertical(size="100%", pad=0.1, sharex=ax[pl, op]) fig.add_axes(ax_top) # 绘制下方轴(低数值段) ax[pl, op].plot(xx, np.mean(some_data[op, pl, :13], axis=0), "-x", color="red") ax[pl, op].set_ylim(0, 25) ax[pl, op].spines['top'].set_visible(False) ax[pl, op].tick_params(axis='x', top=False) # 绘制上方轴(高数值段) ax_top.plot(xx, np.mean(some_data[op, pl, 13:26], axis=0), "-x", color="blue") ax_top.set_ylim(50, 65) ax_top.spines['bottom'].set_visible(False) ax_top.tick_params(axis='x', bottom=False, labelbottom=False) # 添加断轴斜切标记 slash_kwargs['transform'] = ax[pl, op].transAxes ax[pl, op].plot((-slash_len, slash_len), (-slash_len, slash_len), **slash_kwargs) ax[pl, op].plot((1-slash_len, 1+slash_len), (-slash_len, slash_len), **slash_kwargs) slash_kwargs['transform'] = ax_top.transAxes ax_top.plot((-slash_len, slash_len), (1-slash_len, 1+slash_len), **slash_kwargs) ax_top.plot((1-slash_len, 1+slash_len), (1-slash_len, 1+slash_len), **slash_kwargs) # 子图标题放在上方轴顶部,避免被轴间隙截断 ax_top.set_title(f"pl={pl}, op={op}", pad=10) # 统一设置所有子图x轴范围,实现全局x轴共享效果 for row in ax: for sub_ax in row: sub_ax.set_xlim(xx.min(), xx.max()) plt.show()
关键配置说明
- 不要在
plt.subplots初始化阶段直接开全局sharex/sharey,否则新增的断轴会出现刻度冲突,手动统一设置轴范围即可实现共享效果 - 两个断轴段只绘制对应数值区间的数据,不要把全量数据同时画在两个轴上,避免出现线条截断异常
- 斜切标记是断轴的核心视觉标识,不要省略
- 如果需要做横向断轴,把
new_vertical替换为new_horizontal,对应调整左右边框隐藏逻辑、断轴标记位置即可,这套逻辑支持任意行列数的子图网格,不限于3×3布局。
内容的提问来源于stack exchange,提问作者Shaun
相关产品推荐
相关产品推荐

