Matplotlib绘制同一数据时出现平线与正确线条差异问题
问题:同一初始数据在不同图表中显示异常
同一数据FTBS_nonlin_out[0.0](蓝色线条)在plot2中显示为真实波形,在plot1中却显示为平线,已在Python3.8、3.10及多个内核环境测试,仍无法定位异常原因。
相关代码实现
import numpy as np import pandas as pd import matplotlib.pyplot as plt #Global Variables #============== L, J = 100, 100 dx = L/J c = 1 #velocity shape = lambda x: 5*np.sin(x/np.pi) feature = slice(40,50) times = (0,4,8,20) #functions #============== def step(func, signal:pd.DataFrame, steps:tuple|list|np.ndarray|pd.DataFrame, *args, dt=0.5, **kwargs): for n in np.round(np.arange(0, steps[-1]+dt, dt), 3): t1 = np.round(n+dt,3) signal[t1] = np.nan data = func(signal, n, t1, dt, *args, **kwargs) return data def _0State(feature:slice, func): #Creates the innitial signal signal = np.zeros(J+1) signal[feature] = [func(element) for element in list(range(len(signal[feature])))] signal = pd.DataFrame(signal, index=np.linspace(0,L,J+1), columns=[0.0]) signal.index.name = 'x' return signal #===================================== def FTBS_nonlin(signal:pd.DataFrame, t, t1, dt): #u_i^{n+1} = u_{i}^{n} - u_{i}^{n} \frac{\Delta t}{\Delta x}(u_{i}^{n} - u_{i-1}^{n}) for i, row in signal.iloc[1:].iterrows(): signal.loc[i, t1] = row[t] - row[t] * (dt/dx) * (row[t] - signal.loc[i-1,t]) return signal signal = _0State(feature, shape) FTBS_nonlin_out = step(FTBS_nonlin, signal.copy(), times) fig, ax1 = plt.subplots() ax1.set_xlabel('x') ax1.set_ylabel('θ') ax1.plot(FTBS_nonlin_out[0.0]) ax1.plot(FTBS_nonlin_out[4]) plt.legend() plt.title('plot') plt.show() fig, ax1 = plt.subplots() ax1.set_xlabel('x') ax1.set_ylabel('θ') ax1.plot(FTBS_nonlin_out[0.0]) ax1.plot(FTBS_nonlin_out[2]) plt.legend() plt.title('plot2') plt.show()
原因分析
- 数值耗散导致幅值快速衰减:使用的FTBS(迎风差分)格式本身存在数值耗散,叠加非线性方程迭代后,初始波形的幅值会随时间急剧衰减。到
t=4时,FTBS_nonlin_out[4.0]的数据幅值已趋近于0,而初始数据FTBS_nonlin_out[0.0]的幅值最大为5。 - y轴范围自动压缩:matplotlib会根据所有绘制数据自动调整坐标轴范围。plot1中同时绘制了幅值接近0的
t=4数据和幅值为5的初始数据,y轴范围被压缩到接近0的区间,导致初始数据的波形被挤压成看似平线的状态;而plot2中t=2的数据幅值尚未衰减到极小,y轴范围能覆盖初始数据的幅值,因此波形正常显示。
解决办法
- 显式指定y轴范围,确保初始数据幅值在显示区间内:在plot1代码中添加
ax1.set_ylim(-0.5, 5.5); - 给绘图添加标签,明确图例对应关系:比如
ax1.plot(FTBS_nonlin_out[0.0], label='t=0')、ax1.plot(FTBS_nonlin_out[4.0], label='t=4'),再调用plt.legend(); - 使用正确的浮点数列名访问数据:将
FTBS_nonlin_out[4]改为FTBS_nonlin_out[4.0],FTBS_nonlin_out[2]改为FTBS_nonlin_out[2.0],避免索引匹配错误。
内容的提问来源于stack exchange,提问作者JSBG
相关产品推荐
相关产品推荐

