如何将FFT频谱图的X轴频率值转换为有意义的时间周期?
问题:将FFT得到的频率值转换为有意义的时间周期指标
本人是编程新手,现有一份跨度为一年、采样间隔15分钟的电池SOC(State of Charge)时间序列数据,希望通过FFT分析识别小时、周、月等充放电周期。编写了如下代码:
from numpy.fft import fft, fftfreq, ifft import matplotlib.pyplot as plt, mpld3 import numpy as np # 注:原代码遗漏numpy导入,建议补充 # setup domain # number of points (15 min intervals within 1 year) nl = 34943 # length of watched domain # 1 year in hours lx = 34943/4 # creating x-axis x = np.linspace(0, lx, nl) # full signal # dataset of different values throughout the year y = np.array(df['SOC_batt']) # creating necessary frequencies freqs = fftfreq(nl) # splitting frequencies in half mask = freqs > 0 # fft values fft_vals = fft(y) # true theoretical fft fft_theo = 2.0*np.abs(fft_vals/nl) plt.figure(1) plt.title('original data') plt.plot(x, y, color='xkcd:salmon') plt.figure(2) # fft processed plt.plot(freqs[mask], fft_theo[mask], label='true fft values') plt.title('true fft values') mpld3.display()
运行代码后得到FFT频谱图,放大后获取到峰值对应的X轴频率值:
# first peak of 4 at 0.01041 # second peak of 5 at 0.02083 # third peak of 1.1 at 0.03125
现咨询如何将这些频率值转换为与全年数据相关的、更有意义的时间周期指标?
解决方案
核心转换逻辑
FFT输出的频率单位由采样间隔和x轴定义决定:
- 你当前用
fftfreq(nl)得到的频率,单位是每采样点的周期数(每个采样点对应15分钟/0.25小时) - 要得到时间周期(完成一次充放电循环的时长),只需基于采样间隔做倒数换算:
周期(小时) = 采样间隔(小时) / 频率值
代入峰值计算验证
你的采样间隔是0.25小时,代入三个峰值频率:
- 第一个峰值(0.01041):
0.25 / 0.01041 ≈ 24小时(正好是日周期) - 第二个峰值(0.02083):
0.25 / 0.02083 ≈ 12小时(半日周期,对应一天两次充放电) - 第三个峰值(0.03125):
0.25 / 0.03125 = 8小时(每8小时一次循环)
优化代码:直接显示周期(更直观)
修改代码,让频谱图直接以小时/天为单位展示周期,同时修正原代码的细节问题:
from numpy.fft import fft, fftfreq, ifft import matplotlib.pyplot as plt, mpld3 import numpy as np nl = 34943 dt = 0.25 # 采样间隔:0.25小时(15分钟) lx = nl * dt # 总时长:采样点数×采样间隔,计算更准确 x = np.linspace(0, lx, nl) y = np.array(df['SOC_batt']) # 传入采样间隔dt,直接得到「每小时周期数」为单位的频率 freqs = fftfreq(nl, d=dt) mask = freqs > 0 fft_vals = fft(y) fft_theo = 2.0 * np.abs(fft_vals / nl) # 计算周期(小时) periods = 1 / freqs[mask] plt.figure(2) plt.plot(periods, fft_theo[mask], label='FFT amplitude vs period') plt.xlabel('Period (hours)') plt.ylabel('Amplitude') plt.title('FFT Spectrum (Period Domain)') plt.xscale('log') # 对数轴更易区分小时/天/周等不同尺度的周期 plt.grid(True) mpld3.display()
转换为更大时间单位
如果需要将周期转换为天、周、月,直接做单位换算即可:
- 1天 = 24小时
- 1周 = 168小时
- 1月 ≈ 730小时(按30.4天计算)
比如24小时=1天,若后续发现对应频率0.000114的峰值,计算得周期为8760小时=365天(年周期)。
内容的提问来源于stack exchange,提问作者jenzoh
相关产品推荐
相关产品推荐

