如何在循环生成的Matplotlib分面图中共享次Y轴
解决Matplotlib分面图次Y轴共享问题
问题描述
需通过循环指定行列数创建分面图,要求所有子图共享左侧主Y轴(对应ys数据)和右侧次Y轴(对应zs数据)。当前主Y轴与X轴已实现共享,但次Y轴未达到预期:刻度范围不统一,且标签显示不符合“仅外侧子图显示”的要求,需保留行列循环逻辑以适配大量子图场景。
解决方案
要让次Y轴与主Y轴表现一致,需完成两个核心操作:
- 统一所有次Y轴的刻度范围:先计算所有次Y轴数据的全局极值,再为每个次Y轴设置相同刻度范围
- 控制次Y轴刻度标签显示:仅保留最右侧列的子图显示次Y轴标签,其余子图仅显示刻度
修改后的代码
import numpy as np import matplotlib.pyplot as plt # 生成数据 x = np.arange(0, 10, 0.1) y1 = x**2 y2 = 0.5 * x**2 y3 = 1.5 * x**2 y4 = 2 * x**2 ys = [y1, y2, y3, y4] # 修正原代码变量名错误 z1 = -10 * y1 z2 = -11 * y2 z3 = -10.5 * y3 z4 = -9 * y4 zs = [z1, z2, z3, z4] cols = 2 rows = 2 k = 0 # 初始化主图,共享X和主Y轴 fig, ax = plt.subplots(rows, cols, sharex=True, sharey=True, figsize=(10, 8)) # 计算次Y轴数据的全局极值,用于统一刻度范围 all_z_data = np.concatenate(zs) z_min, z_max = all_z_data.min(), all_z_data.max() for i in range(cols): for j in range(rows): # 绘制主Y轴数据 ax[j, i].plot(x, ys[k], c='b') ax[j, i].tick_params(colors='b') # 创建次Y轴并绘制数据 ax2 = ax[j, i].twinx() ax2.plot(x, zs[k], c='r') ax2.tick_params(colors='r') # 设置统一的次Y轴刻度范围 ax2.set_ylim(z_min, z_max) # 控制次Y轴标签显示:仅最右侧列显示标签 if i != cols - 1: ax2.set_yticklabels([]) k += 1 plt.tight_layout() plt.show()
关键说明
- 统一刻度范围:通过
np.concatenate(zs)合并所有次Y轴数据,计算全局最小/最大值后,用set_ylim()为每个次Y轴设置相同范围 - 控制标签显示:通过判断列索引
i是否为最后一列,决定是否隐藏次Y轴的刻度标签,保留刻度线 - 修正原代码问题:原代码中变量
y定义后使用时写为ys,已修正为统一的ys - 优化布局:添加
plt.tight_layout()自动调整子图间距,避免标签重叠
内容的提问来源于stack exchange,提问作者Brendan031
相关产品推荐
相关产品推荐

