Python使用scipy绘制FFT图如何设置0-100Hz范围让峰值居中
问题根因与修正方案
错误操作的本质问题
- 直接修改
xf的生成范围,本质是篡改了FFT频点与真实物理频率的映射关系,并非调整坐标轴的显示范围。 - 原始代码中
xf = np.linspace(0.0, 1.0/(2.0*T), N//2)生成的是和FFT结果严格绑定的正确频率轴:根据奈奎斯特采样定理,单边FFT的有效频率范围是0到奈奎斯特频率(值为1/(2T)),本次代码中采样间隔T=1/800s,对应奈奎斯特频率为400Hz;生成的300个频点(即N//2=300个点),和截取后的半长FFT结果yf[:N//2]一一对应,每个频点的数值就是该FFT采样点对应的真实频率。 - 将
xf范围硬改为0-100Hz后,原本对应0-400Hz的300个FFT采样点,会被强行映射到0-100Hz的坐标区间内,每个点的坐标值被压缩为原真实频率的1/4:原本对应50Hz的FFT采样点大概在第38个序列位置,映射后的坐标为38*(100/300)≈12.7Hz;对应80Hz的FFT采样点大概在第60个序列位置,映射后的坐标为60*(100/300)=20Hz,和你观测到的峰值偏移到11Hz、20Hz的现象完全吻合——全程FFT计算结果没有任何变化,只是x轴的坐标值被错误赋值了。
正确实现方法
- 完整保留原有
xf的生成逻辑,不要改动频点和真实频率的绑定关系。 - 调用matplotlib的坐标轴范围设置接口,仅调整视图的展示区间,不改动底层数据的映射规则:
- 基础需求(x轴仅显示0-100Hz区间):直接添加
ax.set_xlim(0, 100)即可,两个峰值会准确落在50Hz、80Hz的对应位置。 - 优化展示效果(让两个目标峰值在视图中居中):50Hz和80Hz的中点为65Hz,可根据视觉需求微调x轴上下限,比如设置
ax.set_xlim(20, 110),既覆盖0-100Hz的观测范围,也能让两个峰值处于视图核心区域,避免贴边。
- 基础需求(x轴仅显示0-100Hz区间):直接添加
修正后的可运行代码
import numpy as np import matplotlib.pyplot as plt import scipy.fftpack # 采样点总数 N = 600 # 采样间隔 T = 1.0 / 800.0 x = np.linspace(0.0, N*T, N) # 生成50Hz+80Hz的合成正弦信号 y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x) # 计算FFT yf = scipy.fftpack.fft(y) # 保留原有正确的频率轴生成逻辑,不做修改 xf = np.linspace(0.0, 1.0/(2.0*T), N//2) fig, ax = plt.subplots() ax.plot(xf, 2.0/N * np.abs(yf[:N//2])) # 设置x轴显示范围,可根据展示需求调整上下限实现峰值居中 ax.set_xlim(20, 110) plt.show()
内容的提问来源于stack exchange,提问作者user1068636
相关产品推荐
相关产品推荐

