如何修正Python非周期温度信号FFT绘图,正确显示频率分布?
温度信号FFT振幅-频率图异常修复方案
问题分析
当前FFT结果仅在0Hz出现大峰值,核心原因有三点:
- 温度信号包含直流分量(整体均值不为0),这部分能量在FFT中会被集中到0Hz,完全掩盖其他频率的信号特征
- 直接绘制完整FFT结果,包含对称的正负频率,重复展示会干扰有效信号的观察
- 未对FFT振幅做归一化处理,数值量级过大,无法直观呈现其他频率成分
改进步骤
- 去除信号直流分量:将插值后的温度信号减去其均值,消除0Hz的主导能量
- 提取正频率区间:仅保留频率大于0的部分绘图,聚焦有效信号分布
- 振幅归一化:单边频谱的振幅需除以
n/2(n为样本数),让振幅值匹配原始信号的实际波动幅度
修正后的完整代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt def variables(filename, tab=0): # 默认sheet索引为0,避免调用时缺参报错 data = pd.read_excel(filename, sheet_name=tab) return data datafile = variables('data.xlsx') time = datafile['Time_[s]'] temp = datafile['Temperature_[degC]'] # 插值生成等间隔时间序列 dt = 0.1 # 时间步长,对应10Hz采样率 time_inter = np.arange(time[0], time.iloc[-1], dt) # 修正:避免多生成超出原时间范围的点 temp_inter = np.interp(time_inter, time, temp) n = len(temp_inter) # 绘制原始插值信号 plt.plot(time_inter, temp_inter) plt.title('Temp vs Time - time step = 0.1 s') plt.xlabel('Time [s]') plt.ylabel('Temperature [$^\circ$C]') plt.show() # --- FFT处理改进部分 --- # 1. 去除直流分量 temp_inter_dc_removed = temp_inter - np.mean(temp_inter) # 2. 计算FFT fft_output = np.fft.fft(temp_inter_dc_removed) # 3. 获取频率轴 frequencies = np.fft.fftfreq(n, dt) # 4. 提取正频率及对应振幅,同时归一化 positive_freq_mask = frequencies > 0 positive_frequencies = frequencies[positive_freq_mask] # 单边频谱归一化:振幅除以n/2,匹配原始信号幅度 normalized_amplitude = np.abs(fft_output[positive_freq_mask]) * 2 / n # 5. 绘制振幅-频率图 plt.plot(positive_frequencies, normalized_amplitude) plt.xlabel("Frequency [Hz]") plt.ylabel("Normalized Amplitude [$^\circ$C]") plt.title('Amplitude vs Frequency (DC Removed)') plt.grid(True, alpha=0.3) plt.show()
额外说明
- 后续滤波可基于正频率分布,设计巴特沃斯/切比雪夫等滤波器,或直接在频域对目标频率区间的FFT系数置0后做逆FFT
- 插值时修正了
time_inter的生成逻辑,避免超出原始时间序列的最后一个点,保证插值信号的完整性
内容的提问来源于stack exchange,提问作者Davide Sciortino
相关产品推荐
相关产品推荐

