You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于所有子图数据统一自动缩放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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 04:48:29