基于FFT的时间序列转频域代码修正咨询(采样率96000)
FFT频域转换代码修正方案
原代码核心问题
- 频率轴(
linspace)设置逻辑错误:混淆了采样率与数据长度的作用,频率范围和点数计算完全不符合频域分析规则 - 幅值归一化错误:用采样率而非数据长度做归一化基准,且切片范围与频率轴不匹配
- 绘图变量不一致:时域绘图未关联正确的信号数据,且时间与频率轴强行共享导致逻辑混乱
修正后的完整代码
import numpy as np import matplotlib.pyplot as plt # 假设time_series为你的时间序列信号,df为包含时间列的DataFrame data = time_series sample_length = len(data) fs = 96000 # 采样率(Hz) # 执行FFT变换 fft_result = np.fft.fft(data) # 生成正确的频率轴:范围0到Nyquist频率(fs/2),点数对应正频率分量数量 freq_axis = np.linspace(0.0, fs/2, int(sample_length/2) + 1) # 计算幅值并归一化:直流分量不加倍,其余正频率分量加倍(合并对称的负频率能量) amplitude = np.abs(fft_result) / sample_length amplitude[1:-1] *= 2 # 排除直流和Nyquist分量 # 提取正频率部分的幅值 pos_amplitude = amplitude[:int(sample_length/2) + 1] # 绘图 fig, axs = plt.subplots(2, gridspec_kw={'hspace': 0.3}) plt.suptitle('时域与频域波形', fontsize=30) # 时域波形图 axs[0].plot(df.iloc[:, 0], data) axs[0].set_xlabel('时间', fontsize=20) axs[0].set_ylabel('Q0', fontsize=20) # 频域幅值图 axs[1].plot(freq_axis, pos_amplitude, color='g') axs[1].set_xlabel('频率(Hz)', fontsize=20) axs[1].set_ylabel('幅值', fontsize=20) plt.show()
关键修正说明
频率轴计算
频域分析中,有效频率范围是0到fs/2(Nyquist频率),频率点数量等于数据长度的一半加1(包含直流分量),确保与FFT正频率分量的数量完全匹配。幅值归一化
FFT结果的幅值需除以数据长度还原到原始信号的幅值量级,同时对除直流和Nyquist分量外的正频率分量乘以2,因为FFT结果中正负频率分量对称,我们仅保留正频率部分,需合并对应能量。绘图逻辑优化
取消时间轴与频率轴的共享(单位完全不同,无共享意义),同时明确时域绘图的时间列与信号数据的对应关系。
内容的提问来源于stack exchange,提问作者Aditya Bhandwalkar
相关产品推荐
相关产品推荐

