如何修复Matplotlib 2×2子图y轴刻度不一致问题
统一Matplotlib 2×2子图Y轴刻度的解决方案
我在处理多工作表Excel文件的压缩测试数据时,用Matplotlib绘制了2×2布局的子图,但发现各子图的Y轴刻度不一致,而实际需求是让所有子图的Y轴刻度保持统一。
示例代码如下:
import numpy as np import pandas as pd import matplotlib.pyplot as plt fig, axes = plt.subplots(2, 2, constrained_layout=True, figsize=(7,7),) height=6 diameter=13 Circle_area=3.14159265359*((diameter/2)**2) Dark2_colors=['seagreen','chocolate','slateblue','deeppink','yellowgreen'] # 假设sheetnames是已定义的工作表名称列表 sheetnames = ["sheet1", "sheet2", "sheet3", "sheet4"] for i in np.arange(0,len(sheetnames),1): label=sheetnames[i] df = pd.read_excel('filename.xlsx',sheet_name = sheetnames[i] ,header= None) df = df.iloc[3:] #移除前3行 df.rename(columns = {0:'Standard travel[mm]', 1:'Standard force[N]'},inplace=True)#重命名列 df['Strain']=(df['Standard travel[mm]']/height)*100 df['Stress']=(df['Standard force[N]']/Circle_area) y = df['Stress'] x = df['Strain'] if i==0: axes[0,0].plot(x, y, linewidth=1, c=Dark2_colors[i], label=label) elif i==1: axes[0,1].plot(x, y, linewidth=1, c=Dark2_colors[i], label=label) elif i==2: axes[1,0].plot(x, y, linewidth=1, c=Dark2_colors[i], label=label) elif i==3: axes[1,1].plot(x, y, linewidth=1, c=Dark2_colors[i], label=label) for ax in axes.flat: ax.set_xlabel('Compressive Strain [%]',fontsize=14,fontweight='bold') ax.set_ylabel('Compressive Stress [MPa]',fontsize=14,fontweight='bold') for ax in axes.flat: ax.label_outer() for ax in axes.flat: ax.legend() plt.show()
注:原代码中plot函数存在多余逗号,已修正;同时添加了label参数,确保图例正常显示。
问题原因
Matplotlib默认会根据每个子图的数据集范围自动计算并设置Y轴刻度,当不同子图的数据范围存在差异时,就会出现刻度不一致的情况。
解决方案
方法1:共享Y轴刻度(最简单)
在创建子图时设置sharey=True,让所有子图共享同一个Y轴刻度,Matplotlib会自动基于所有数据的范围统一设置刻度:
fig, axes = plt.subplots(2, 2, constrained_layout=True, figsize=(7,7), sharey=True)
这样所有子图的Y轴会使用相同的刻度范围,无需额外计算。
方法2:手动统一Y轴范围
如果需要更精细地控制刻度范围,可以先遍历所有数据,计算出全局的Y轴最小值和最大值,再统一设置所有子图的Y轴范围:
# 先收集所有Y轴数据 all_stress = [] for sheet in sheetnames: df = pd.read_excel('filename.xlsx', sheet_name=sheet, header=None) df = df.iloc[3:] df.rename(columns={0:'Standard travel[mm]', 1:'Standard force[N]'}, inplace=True) df['Stress']=(df['Standard force[N]']/Circle_area) all_stress.extend(df['Stress'].values) # 计算全局的最小和最大值 global_min = np.min(all_stress) global_max = np.max(all_stress) # 绘制子图(部分代码省略,和原代码一致) # 统一设置所有子图的Y轴范围 for ax in axes.flat: ax.set_ylim(global_min, global_max)
这种方法适合需要自定义刻度范围的场景,比如希望给最大值留出一定余量,可以将global_max乘以1.1。
内容的提问来源于stack exchange,提问作者Ouriel Bliah
相关产品推荐
相关产品推荐

