时间序列的STL分解Python代码——以验潮站数据为例

1.时间序列分解的作用和意义

时间序列通常包括如下几种成分:

一个时间序列包含三种影响因素:

 

长期趋势:在一个相当长的时间内表现为一种近似直线的持续向上、向下或平稳的趋势。

季节变动:受季节变化影响所形成的一种长度和幅度固定的短期周期波动

周期变动:与季节变动类似,但是波动的时间频率不是固定的,通常在时间序列分解中与长期趋势结合成为趋势周期项

不规则变动:受偶然因素的影响所形成的不规则波动,如股票市场受利好或者利空信息的影响,使得股票价格产生的波动

在进行时间序列预测时,时间序列分解可以更直观地查看时间序列的成分,将时间序列数据分解为趋势项、季节项和残差项,后续则可以单独对各项进行时间序列预测并合并。

2.时间序列分解的方法

目前时间序列分解的方法主要包括经典分解法、X11分解法、SEATS分解法、STL分解法、fbprophet分解法等,本文选择STL分解法进行分解。

STL分解法:STL是一种多功能、鲁棒的方法。全称“Seasonal and Trend decomposition using Loess”,其中Loess是一种鲁棒的回归算法。

特点:

  • 与SEATS与X11不同,STL可以处理任意季节性数据,而非局限于月度或季度数据
  • 季节部分可以随时间变化,变化率可以由用户控制。STL的一大特点便是提供对季节性的单独乘法趋势,可以在采用加法型模型时,使加上去的趋势的幅度不断扩大。且该变化率是自动检测的。
  • 趋势周期的平滑度可以由用户控制
  • 可以对异常值鲁棒(使异常值不影响季节部分与趋势部分,但是影响残差),代码中一般有robust=True/False控制。

缺点:

  • 不能自动处理节假日
  • 只能进行加性分解

3.STL分解

在进行分解前,你需要知道的部分参数包括:

period:表示季节性的周期,也就是时间索引的周期,如果原始数据是pandas的series 或dataframe形式代码能够自行判断此参数,但建议自行设置。
season: 表示季节性平滑器的长度,它必须是一个奇数,通常要>=7(默认)。
trend:表示趋势平滑器的长度,通常要>period(或season)的1-1.5倍,并且它必须是一个奇数。默认值是最小的1-1.5倍的period,比如period=7则trend默认值是9,如果period=12则trend默认值是13
使用的库:statsmodels、pandas、seaborn、matplotlib、pylab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import STL
import statsmodels.api as sm
import pylab
from pylab import mpl<br>#导入包的时候比较乱,请见谅....
mpl.rcParams['font.sans-serif'] = ['SimHei']#此步骤是为了解决字体问题
plt.rcParams['axes.unicode_minus']=False#此步骤是为了解决字体问题
plt.rc("figure", figsize=(10, 6))#设置绘图区尺寸
for x in []:#在中括号中输入的是季节平滑器的长度,输入多个则分别导出不同参数下的结果,也可相应修改,添加其他参数
    df=pd.read_csv('C:/Users/Administrator/Desktop/STL.csv',encoding='ANSI',usecols=['time', 'value'],index_col='time') #读取原始数据,这里的time,value是原始数据中的列标签名,此外encoding参数需要根据csv的编码确认,usecols选择使用的列,index_col参数选择索引列
    print(df)#查看读取好的文件
    stl=STL(df,period=12,seasonal=x,robust=False)#因为原始数据是月度数据,这里手动设置了period=12,robust为True时会用一种更严格的方法来约束trend和season,同时也会导致更大的resid
    res=stl.fit()
    res.plot()
    plt.savefig("D:/figures2/{}.png".format(x))#保存STL分解结果图
    plt.clf()#清空绘图区防止重复绘图
    df['trend']=res.trend#保存分解后数据
    df['seasonal']=res.seasonal
    df['resid']=res.resid
    dataframe = pd.DataFrame({'trend':df['trend'],'season':df['seasonal'],'resid':df['resid']})#将分解结果按照列导入csv文件
    dataframe.to_csv("D:/figures2/{}table.csv".format(x),sep=',')
    print('residual mean:',df.resid.mean())#查看残差正态性检验的均值
    mean=df.resid.mean()
    sns.distplot(df.resid)#绘制带正态曲线的概率密度直方图
    plt.savefig("D:/figures2/{}mean={}.png".format(x,mean))
    plt.clf()
    sm.qqplot(df.resid, line='s')#绘制正态检验QQ图
    plt.savefig("D:/figures2/{}QQ.png".format(x))

代码中除了对原始数据进行读取和STL分解外,还包括了如下几个步骤:

(1)将分解后的数据导入至csv文件中以便后续分析和绘图

(2)绘制残差项的直方图和QQ图,判断残差正态性(只有残差项通过正态性检验才说明分解有效)

 

posted @   Victooor_swd  阅读(2249)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示