为何傅里叶变换子图中出现多余水平线?技术问询
FFT绘图时子图底部出现不明水平线的解决方法
问题描述
我正在绘制一组信号的傅里叶变换,每组数据仅包含一组y值,每个子图应仅显示一条曲线,但当前每个子图底部都出现了一条来源不明的水平线。
问题代码
def GenerateFFT(parsedData,T): colors = ["red","green","blue","purple","orange","cyan","pink","black"] parsedDataY=parsedData[1:] print(parsedDataY[len(parsedDataY)-1]) fig, ax = plt.subplots(len(parsedDataY),sharex=True,sharey=True) #FourierValues = [[] for _ in range(4)] for i in range(len(parsedDataY)): signal = np.array(parsedDataY[i],dtype=float) N=signal.size print(f"Signal Size at i={i}: {N}") x=np.arange(30.0,49.035,.005) # 此段代码未被使用,可删除 fourier = np.fft.fft(signal) fourierFreq = np.fft.fftfreq(n=signal.size,d=1.0/T) #FourierValues[i].append(fourier) print(np.sqrt(np.sqrt(fourier.real**2+fourier.imag**2)).tolist) ax[i].plot(fourierFreq,np.sqrt(fourier.real**2+fourier.imag**2),color=colors[i],linewidth=.75) ax[i].set_yscale("log") ax[i].set_xbound(lower=-10,upper=10) plt.setp(ax, xlim=(0,10),ylim=ax[0].get_ylim()) fig.suptitle("Fourier Transforms of Monochromatic Wavetrains with Amplitude Modulation",fontweight="bold") fig.supxlabel("Frequency (Hz)",fontweight="bold") fig.supylabel("Amplitude (cm) on Logarithmic Scale",fontweight="bold") plt.show()
注:parsedData为二维数组,parsedData[0]为时间步长值,其余索引对应y值数组。
问题原因
- 绘制了完整FFT频率范围:
np.fft.fftfreq返回的频率包含正负两部分,直接绘制全部频率时,曲线会在正频率终点与负频率起点间产生跨x轴的跳跃线。虽通过xlim=(0,10)截断x轴,但这条跳跃线的部分片段会在子图底部异常显示。 - 冗余的x轴范围设置:同时使用
set_xbound和plt.setp(ax, xlim=...)重复设置x轴范围,可能引发绘图逻辑冲突。 - 未处理信号异常值:若原始信号存在NaN/inf,FFT结果会出现异常幅值,在对数刻度下可能表现为底部水平线。
修复后的代码
def GenerateFFT(parsedData,T): colors = ["red","green","blue","purple","orange","cyan","pink","black"] parsedDataY=parsedData[1:] print(parsedDataY[-1]) fig, ax = plt.subplots(len(parsedDataY), sharex=True, sharey=True) for i in range(len(parsedDataY)): signal = np.array(parsedDataY[i], dtype=float) # 处理信号中的NaN/inf值,避免FFT结果异常 signal = np.nan_to_num(signal) N = signal.size print(f"Signal Size at i={i}: {N}") fourier = np.fft.fft(signal) fourierFreq = np.fft.fftfreq(n=signal.size, d=1.0/T) # 简化FFT幅值计算,与原公式结果一致 fourier_amp = np.abs(fourier) # 筛选正频率部分,仅绘制有效范围的曲线 positive_mask = fourierFreq > 0 ax[i].plot(fourierFreq[positive_mask], fourier_amp[positive_mask], color=colors[i], linewidth=.75) ax[i].set_yscale("log") # 统一设置x轴范围,移除冗余的set_xbound plt.setp(ax, xlim=(0,10), ylim=ax[0].get_ylim()) fig.suptitle("Fourier Transforms of Monochromatic Wavetrains with Amplitude Modulation", fontweight="bold") fig.supxlabel("Frequency (Hz)", fontweight="bold") fig.supylabel("Amplitude (cm) on Logarithmic Scale", fontweight="bold") plt.show()
关键修改点
- 仅绘制正频率部分的FFT结果,消除正负频率间的跳跃线。
- 用
np.abs(fourier)简化幅值计算,效率更高且结果一致。 - 添加
np.nan_to_num(signal)处理信号异常值,避免FFT产生无效幅值。 - 删除未使用的冗余代码,移除重复的x轴范围设置,统一用
plt.setp控制轴范围。
内容的提问来源于stack exchange,提问作者Riderdie
相关产品推荐
相关产品推荐

