如何用numpy FFT将频谱分析结果输出为精确谐波频率数值列表?
家庭电压信号的谐波频谱提取实现方案
完全可以实现你需要的精准谐波数值列表提取,以下是具体解决步骤和代码,同时针对你无法显示结果/绘图的问题给出排查方向:
核心实现逻辑
利用numpy的FFT工具,通过整周期采样避免频谱泄漏,对齐目标谐波频率点后提取幅值,再转换为百分比占比即可得到你需要的列表。
具体代码实现
import numpy as np # 配置参数 fs = 24000 # 采样频率(Hz) f0 = 50 # 基波频率(Hz) max_target_freq = 2000 # 最高目标谐波频率(Hz) # 假设你的原始电压数据已加载到voltage_data数组中 # 示例:如果没有实际数据,可生成模拟测试数据 # voltage_data = 150 * np.sin(2*np.pi*f0*np.arange(0, 1, 1/fs)) + 18 * np.sin(2*np.pi*3*f0*np.arange(0, 1, 1/fs)) + 18 * np.sin(2*np.pi*5*f0*np.arange(0, 1, 1/fs)) # 第一步:整周期采样,消除频谱泄漏 # 每个基波周期的采样点数:24000/50=480 period_sample_count = fs // f0 # 取整数个周期的有效数据 valid_sample_count = (len(voltage_data) // period_sample_count) * period_sample_count processed_data = voltage_data[:valid_sample_count] # 第二步:执行FFT计算 fft_result = np.fft.fft(processed_data) fft_freqs = np.fft.fftfreq(len(processed_data), 1/fs) # 筛选正频率部分(负频率与正频率对称,无需重复处理) positive_mask = fft_freqs >= 0 positive_freqs = fft_freqs[positive_mask] positive_fft_vals = fft_result[positive_mask] # 第三步:计算实际幅值(FFT结果需要缩放) sample_count = len(processed_data) amplitudes = np.abs(positive_fft_vals) / sample_count amplitudes[1:] *= 2 # 直流分量外,单频信号的幅值需要乘2 # 第四步:提取目标谐波的幅值(0Hz、50Hz、100Hz...2000Hz) target_freqs = np.arange(0, max_target_freq + 1, f0) harmonic_amps = [] for freq in target_freqs: # 找到最接近目标频率的FFT点索引 closest_idx = np.argmin(np.abs(positive_freqs - freq)) harmonic_amps.append(amplitudes[closest_idx]) # 第五步:转换为百分比占比(以基波幅值为100%基准) base_amplitude = harmonic_amps[1] # 50Hz基波的幅值 harmonic_percent = [0.0] # 0Hz分量占比初始为0 for amp in harmonic_amps[1:]: percent = round((amp / base_amplitude) * 100) harmonic_percent.append(percent) # 输出你需要的列表(索引0对应0Hz,索引40对应2000Hz) print(harmonic_percent)
无法显示结果/绘图的排查方向
- 数据加载验证:
- 打印
len(voltage_data)确认数据长度是否合理,打印voltage_data[:10]查看是否有有效数值,排查是否存在NaN、无穷大等异常值。
- 打印
- FFT中间结果检查:
- 打印
positive_freqs[:10]确认频率轴是否正确对齐50Hz的整数倍,打印amplitudes[:10]查看幅值是否符合预期。
- 打印
- 绘图问题解决:
- 如果需要验证绘图,确保已安装matplotlib库(执行
pip install matplotlib),添加以下代码即可绘图:import matplotlib.pyplot as plt plt.stem(target_freqs, harmonic_percent) plt.xlabel('频率(Hz)') plt.ylabel('占比(%)') plt.show()
- 如果需要验证绘图,确保已安装matplotlib库(执行
内容的提问来源于stack exchange,提问作者Bartosz Olejarz
相关产品推荐
相关产品推荐

