如何使用Python查找FFT频谱图峰值并获取对应x轴频率值
问题原因说明
- 复数警告触发原因:
scipy.signal.find_peaks仅接受实值序列作为输入,而FFT运算的输出是包含实部、虚部的复数序列,直接传入会触发虚部丢弃的警告,也会导致峰值计算结果完全不符合预期。 - 无法拿到正确x轴的原因:你当前用的
x是原始数据的时域采样坐标,不是FFT变换后的频域频率坐标,需要单独生成对应的频率轴才能匹配峰值位置。
修复方案
- 对FFT的输出计算幅值(模值),再传入
find_peaks做峰值检测 - 使用
scipy.fft.fftfreq生成与FFT结果一一对应的频率轴,再根据峰值索引提取对应频率值 - 可选:仅保留正频率区间的结果,避免对称的重复峰值干扰
修正后代码
import pandas as pd import matplotlib.pyplot as plt from scipy.fft import fft, fftfreq from scipy.signal import find_peaks import numpy as np headers = ["X","Y"] original_data = pd.read_csv("testdata.csv",names=headers) # 原始时域数据 t = original_data["X"] # 这里是时域采样的时间/位置坐标 y = original_data["Y"] n = len(y) # 计算采样间隔 dt = t[1] - t[0] # 执行FFT并计算幅值 y_fft = fft(y) y_amp = np.abs(y_fft) # 取模得到幅值,消除复数问题 # 生成对应频率轴 freq = fftfreq(n, dt) # 仅保留正频率部分(可选,避免重复峰值) positive_mask = freq >= 0 freq_pos = freq[positive_mask] amp_pos = y_amp[positive_mask] # 检测峰值,可根据需要调整height、threshold等参数筛选有效峰值 peaks_idx, _ = find_peaks(amp_pos) # 提取峰值对应的频率和幅值 peak_freqs = freq_pos[peaks_idx] peak_amps = amp_pos[peaks_idx] print("峰值对应的频率值:", peak_freqs) print("峰值对应的幅值:", peak_amps) # 绘图 plt.plot(freq_pos, amp_pos) plt.scatter(peak_freqs, peak_amps, color='red', label='检测到的峰值') plt.title("Fast Fourier transform") plt.xlabel("Frequency") plt.ylabel("Amplitude") plt.legend() plt.show()
补充说明
如果需要筛选更精准的峰值,可以给find_peaks传入height(最小幅值阈值)、distance(峰值最小间隔)等参数,例如find_peaks(amp_pos, height=10, distance=5)可以过滤掉幅值低于10、间隔小于5个采样点的无效峰值。
内容的提问来源于stack exchange,提问作者MUD
相关产品推荐
相关产品推荐

