如何基于所有子图数据统一自动缩放Matplotlib子图Y轴?
统一Matplotlib双Y轴子图缩放的高效实现
问题场景
你需要循环绘制多组数据的对比子图(线性X轴vs对数X轴),每次绘图后保存并清除线条,目前单张子图会自动缩放Y轴,但希望两个子图基于所有数据使用统一的Y轴范围,同时避免冗余绘图带来的性能损耗。
高效解决方案
核心思路是预先计算所有数据的Y轴全局极值,提前固定两个子图的Y轴范围,这样循环绘图时无需再调整缩放,直接绘制当前数据即可,完全避免冗余操作。
修改后的代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec # -------------------------- # 第一步:预计算全局Y轴极值 # -------------------------- # 合并所有Y数据(线性和对数轴的Y数据都要考虑) all_y_data = [] for i in range(whatever): all_y_data.extend(y_linear[i]) all_y_data.extend(y_log[i]) # 计算全局最小和最大值(适配对数轴,过滤非正数) global_y_min = np.min([y for y in all_y_data if y > 0]) global_y_max = np.max(all_y_data) # -------------------------- # 第二步:初始化画布和子图 # -------------------------- fig = plt.figure(figsize=(12,6)) gs = GridSpec(1, 2, figure=fig, width_ratios=[1, 1]) ax1 = fig.add_subplot(gs[0, 0]) ax2 = fig.add_subplot(gs[0, 1]) # 配置子图属性并固定Y轴范围 ax1.set_xlabel(r"$x$") ax1.set_yscale("log") ax1.set_ylabel(r"$f(x)$") ax1.set_ylim(global_y_min, global_y_max) # 锁定Y轴缩放 ax2.set_xscale("log") ax2.set_xlabel(r"$x$") ax2.set_yscale("log") ax2.set_ylabel(r"$f(x)$") ax2.set_ylim(global_y_min, global_y_max) # 与ax1保持完全一致 # -------------------------- # 第三步:循环绘图 # -------------------------- for i in range(whatever): # 绘制当前组数据 ax1.plot(x_linear[i], y_linear[i]) ax2.plot(x_log[i], y_log[i]) # 保存图片 fig.savefig(f"{i}.png") # 清除当前线条,准备下一组绘图 for line in ax1.get_lines(): line.remove() for line in ax2.get_lines(): line.remove()
关键说明
- 预计算全局Y极值:仅遍历一次所有数据,一次性确定两个子图的Y轴范围,避免循环中反复调整缩放的开销
- 固定Y轴范围:通过
set_ylim直接锁定缩放比例,确保两个子图Y轴完全对齐,无需再调用relim()和autoscale() - 性能优化:全程仅遍历数据两次(一次计算极值,一次绘图),完全避免冗余绘图或透明线的额外性能损耗
内容的提问来源于stack exchange,提问作者campioru
相关产品推荐
相关产品推荐

