You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用scipy.fft提取时间序列中最常见的周期频率

如何使用scipy.fft提取时间序列中最常见的周期频率

我明白你的困扰——看着时间序列里明显的12个月周期,却不知道怎么用scipy.fft把这个频率精准提取出来。别担心,咱们一步步来解决这个问题:

首先还原你的问题场景:你有一个带周期性的时间序列(可视化图如下),能看到每12个月左右就会出现涨跌循环,偶尔会在11-13个月波动,现在想通过傅里叶变换找到这个最显著的周期。

时间序列周期性可视化

完整解决方案代码&步骤

第一步:准备数据和依赖库

先把你的数据转成NumPy数组,同时导入需要的工具库:

import numpy as np
from scipy.fft import fft, fftfreq
import matplotlib.pyplot as plt

# 加载你的数据
data = np.array([
    11130.578853063385,
    6509.723592808,
    5693.928982796129,
    3415.099921325464,
    -9299.291673374173,
    -3388.284173885658,
    -5577.9316298032745,
    -3509.583232678111,
    2285.99065857961,
    3844.3061166856014,
    -7383.526882168155,
    -4622.792125020905,
    2813.586128745183,
    -1501.9405075290495,
    8911.954971658348,
    7800.444458471794,
    -1190.7952377053866,
    4768.791467877524,
    2173.593871988719,
    -2420.04786197912,
    -2304.842777539399,
    -3562.1788525161837,
    -8766.208378658988,
    -7655.936603573945,
    -5890.9298543619125,
    -9628.764012284291,
    12124.740839506767,
    12391.257220312522,
    7512.253051850619,
    12921.032383220418,
    10063.270097922614,
    -1350.2599176773563,
    -6887.434936788105,
    -11116.26528794868,
    -10196.871058658888,
    -10874.172006461778,
    -15014.190086779208,
    -17837.744786550902,
    15235.434771455053,
    17183.25815161994,
    16835.95193044929,
    21063.986176551374,
    17987.99577807288,
    -270.6290142721815,
    -11239.957979217992,
    -18724.854251002133,
    -11752.820614075652,
    -14332.597031388648,
    -24609.22398631297,
    -26155.98046224267,
    18192.356438131075,
    22165.14150786262,
    26758.419290443217,
    29284.65841543005,
    25762.928479462924,
    865.3393849464444,
    -15121.264730579132,
    -26306.45361387036,
    -13494.286360139175,
    -18089.58324839494,
    -34738.184049794625,
    -34718.87495981627,
    21145.112760626133,
    27322.030709198487,
    37252.78168890166,
    37846.98231395838,
    33206.62103950547,
    2092.870600583023,
    -18537.521405900694,
    -33955.48182565038,
    -15445.551953312479,
    -22284.152196532646,
    -45880.94206326016,
    -44229.92788481257,
    24988.038646046363,
    32958.71017047145,
    49117.93320642349,
    47304.760779654374,
    40776.01828187993,
    3403.573579093782,
    -22402.79273128273,
    -42361.96378730598,
    -17190.060741565456,
    -27378.2527904574,
    -59155.49212555031,
    -60122.10588005664,
    26272.133100405994,
    44887.192435244986,
    69002.74742137044,
    59037.928523261784,
    42122.51604012313,
    6075.663868325184,
    -20631.710295791454,
    -48088.66531781877,
    -23396.29341809641,
    -40847.479839729145,
    -68317.87342502769,
    -73679.4424942532,
    28302.69374713241,
    57321.16868946109,
    83820.10748232565,
    68399.66173487401,
    44989.374076533895,
    8830.088516704302,
    -18149.500187183363,
    -52028.5021898363,
    -31013.963236266634,
    -53956.5249205745,
    -77250.59604604884,
    -86642.45203443282,
    30541.62328593645,
    69812.47143595785,
    98233.7834300242,
    77385.915451272,
    48189.69475295938,
    11504.22579592029,
    -15251.799652343976,
    -55879.292898282,
    -38956.992207762654,
    -67210.9936142441,
    -86636.69916492153,
    -99845.12467446178,
    32751.253099701484,
    82656.01928819218,
    113259.2399845611,
    86532.20966362985,
    51019.20889397171,
    14289.09297146163,
    -11777.371574335935,
    -59627.30976102835,
    -47170.18721199697,
    -81027.36407627042,
    -96178.09587995053,
    -113526.93736260894,
    34817.23859755824,
    95927.57143777516,
    128782.84687524068,
    95920.65382048927,
    53226.62965224956,
    17272.000877533148,
    -7716.869736424804,
    -63110.06727848651,
    -55696.68126167806,
    -95538.60898488457,
    -105325.08525283691,
    -127600.17956244369,
    36734.97589442811,
    109601.51109750797,
    144205.71977383518,
    105517.48123365057,
    54793.814706888734,
    20380.77940730315,
    -3119.1108027357986,
    -66153.73274186133,
    -64702.85998743505,
    -110650.72884973585
])

# 假设数据是按月采集的,采样间隔为1个月
sampling_interval = 1  # 单位:月
n = len(data)

第二步:执行傅里叶变换并计算频率

fft计算傅里叶变换,fftfreq生成对应的频率轴(注意只保留正频率,因为FFT结果是对称的):

# 计算FFT
yf = fft(data)
# 生成频率轴(单位:1/月)
xf = fftfreq(n, sampling_interval)

# 筛选出正频率部分,避免重复计算
positive_mask = xf > 0
xf_positive = xf[positive_mask]
yf_positive = np.abs(yf[positive_mask])  # 取复数的绝对值作为幅度,代表该频率的强度

第三步:提取主导周期

傅里叶变换中幅度最大的频率,就是数据里最显著的周期对应的频率,我们把它转成周期(周期=1/频率):

# 找到幅度最大的频率索引
max_amp_index = np.argmax(yf_positive)
dominant_frequency = xf_positive[max_amp_index]
# 计算对应的周期
dominant_period = 1 / dominant_frequency

print(f"提取到的最显著周期为:{dominant_period:.2f} 个月")

第四步:可视化频谱(可选)

如果想直观看到各个频率的强度,可以画个频谱图,还能标记出我们找到的主导周期:

plt.figure(figsize=(10, 6))
plt.plot(xf_positive, yf_positive)
plt.xlabel('频率 (1/月)')
plt.ylabel('幅度')
plt.title('时间序列频谱图')
# 标记主导周期对应的点
plt.scatter(dominant_frequency, yf_positive[max_amp_index], color='red', label=f'主导周期:{dominant_period:.2f}个月')
plt.legend()
plt.show()

几个关键注意点

  1. 采样间隔:这里假设数据是按月采集的,所以采样间隔设为1个月。如果你的数据采样频率不同(比如每周一次),记得调整这个值,不然周期计算会出错。
  2. 正频率筛选:FFT的结果是对称的,负频率和正频率信息重复,所以只看正频率就够了。
  3. **幅度取

火山引擎 最新活动