
matplotlib 在绘制多条数据时,若某条数据存在极端异常值,会自动扩展 y 轴范围,致使其他正常数据的波动在视觉上被压缩成一条“扁平线”,实则并非数据错误,而是坐标尺度失衡所致。
该问题本质是 Matplotlib 自动设置 y 轴范围(ylim)时,被某列数据中的极大/极小异常值主导,从而掩盖了其余数据的真实形态。在您的代码中:
ax1.plot(FTBS_nonlin_out[0.0]) # 初始状态:幅度约 [-5, 5] ax1.plot(FTBS_nonlin_out[4]) # t=4 时刻:含数值爆炸(如 -2e18)
FTBS_nonlin_out[4] 列因 FTBS 格式在非线性对流方程中缺乏耗散或稳定性控制(尤其当 c * dt / dx > 1 时),极易产生数值震荡与溢出,导致个别元素达到 ~ -1e18 量级。而 ax1.plot() 默认将所有传入数据的最大最小值作为绘图边界,因此 y 轴被拉伸至 [-2e18, 5] —— 此时幅度仅 ±5 的初始状态 FTBS_nonlin_out[0.0] 在像素级图像中几乎无法分辨,呈现为视觉上的“水平直线”。
✅ 验证方法:添加以下调试语句即可确认:
print("t=0.0 range:", FTBS_nonlin_out[0.0].min(), FTBS_nonlin_out[0.0].max())
print("t=4 range: ", FTBS_nonlin_out[4].min(), FTBS_nonlin_out[4].max())✅ 解决方案(推荐组合使用):
-
显式限制 y 轴范围(快速诊断 & 可视化修复):
ax1.set_ylim(-30, 30) # 或 plt.ylim(-30, 30)
-
过滤异常值再绘图(保障展示合理性):
# 仅绘制有限数值(排除 inf / nan / 极端离群点) valid_0 = FTBS_nonlin_out[0.0].replace([np.inf, -np.inf], np.nan).dropna() valid_t4 = FTBS_nonlin_out[4].replace([np.inf, -np.inf], np.nan).dropna() ax1.plot(valid_0.index, valid_0, label='t=0.0') ax1.plot(valid_t4.index, valid_t4, label='t=4')
-
根本性改进数值稳定性:
- 检查 CFL 条件:确保 c * dt / dx ≤ 1(当前 c=1, dt=0.5, dx=1.0 → CFL=0.5,合规,但非线性项可能引发隐式超限);
- 改用更稳定格式(如 Lax-Wendroff、ENO/WENO)或添加人工粘性;
- 对更新公式做截断保护(防御性编程):
u_new = row[t] - row[t] * (dt/dx) * (row[t] - signal.loc[i-1,t]) signal.loc[i, t1] = np.clip(u_new, -1e3, 1e3) # 防止爆炸
? 总结:这不是 Matplotlib 的 bug,而是数值模拟中“结果失稳 → 数据污染绘图范围 → 可视化失效”的典型链式现象。务必养成先检查数据分布、再绘图的习惯;在科研可视化中,plt.ylim() 不是妥协,而是必要控制手段;而长期来看,算法稳定性永远比绘图技巧更重要。









