时间序列平稳性判断
时序图检验
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# 读取某销售数据
# squeeze参数:当只有一个列时,返回Series类型
data = pd.read_csv('./data/catfish.csv',parse_dates=[0],squeeze=True,index_col= 0)
data.head(3)
Date
1986-01-01 9034
1986-02-01 9596
1986-03-01 10558
Name: Total, dtype: int64
plt.figure(figsize=(10,4))
plt.plot(data['2000-01-01':'2004-01-01'])
for year in range(2000,2004):
plt.axvline(pd.to_datetime(str(year)+'-01-01'),linestyle = '--',alpha = 0.3)
plt.axhline(data['2000-01-01':'2004-01-01'].mean(),alpha=0.3,linestyle='--')
plt.show()
plt.figure(figsize=(15,4))
plt.plot(data['1986-01-01':'2004-01-01'])
for year in range(1986,2004):
plt.axvline(pd.to_datetime(str(year)+'-01-01'),linestyle = '--',alpha = 0.3)
plt.axhline(data['1986-01-01':'2004-01-01'].mean(),alpha=0.3,linestyle='--')
plt.show()
从短期时序图可以看出,销售额以一年为周期上下起伏,具有周期性
从长期时序图可以看出,销售额随着时间逐渐增长,具有趋势性
因此此序列是不平稳序列
自相关图检验
若自相关系数随着延迟期数k的增加,很快衰减向零,则一般是平稳序列
from statsmodels.graphics.tsaplots import plot_acf
# plot_acf(x, ax=None, lags=None, *, alpha=0.05, use_vlines=True,
# adjusted=False, fft=False, missing='none', title='Autocorrelation',
# zero=True, vlines_kwargs=None, **kwargs)
#alpha:置信区间范围
#lags:绘制的k的最大值
plot_acf(data,lags=25)
from statsmodels.tsa.stattools import acf
#acf(x, adjusted=False, nlags=None, qstat=False, fft=None, alpha=None, missing='none')
# 计算自相关系数
# qstat:是否进行Q检验(白噪声检验)
# adjuest:是否使用n-k作为计算分母
# alpha:若给定,则返回acf的置信区间
# 函数返回:
# acf_values: 不同滞后数lag的自相关系数
# confint: 自相关系数的置信区间
# q_stat: Ljung-box统计量(判断时间序列是否有随机性)
# p_values: q_stat对应的P值,<aplha则拒绝原假设:时间序列是白噪声序列(纯随机序列)
acf_vals = acf(data)
plt.bar(range(25),acf_vals[:25])
C:\Users\lipan\anaconda3\lib\site-packages\statsmodels\tsa\stattools.py:568: FutureWarning: fft=True will become the default in a future version of statsmodels. To suppress this warning, explicitly set fft=False.
warnings.warn(
<BarContainer object of 25 artists>
可以看到自相关系数随着K的增加,下降趋势缓慢
都在>0的一侧,说明序列具有趋势性
有周期性增减,说明具有周期性
纯随机性检验
首先将时间序列进行一阶差分,将其平稳化
data_diff = data.diff()[1:]
plt.figure(figsize=(15,4))
plt.plot(data_diff['1986-01-01':'2004-01-01'])
for year in range(1986,2004):
plt.axvline(pd.to_datetime(str(year)+'-01-01'),linestyle = '--',alpha = 0.3)
plt.axhline(data_diff['1986-01-01':'2004-01-01'].mean(),alpha=0.3,linestyle='--')
plt.show()
LB检验
# acorr_ljungbox(x, lags=None, boxpierce=False, model_df=0, period=None, return_df=None, auto_lag=False)
# lags:为延迟期数,如果为整数,则是包含在内的延迟期数,如果是一个列表或数组,那么所有时滞都包含在列表中最大的时滞中
# boxpierce:为True时表示除开返回LB统计量还会返回Box和Pierce的Q统计量
# model_df:模型自由度
# periods: 季节性周期长短
# 返回值:
# lbvalue:测试的统计量
# pvalue:基于卡方分布的p统计量
# bpvalue:((optionsal), float or array) – 基于 Box-Pierce 的检验的p统计量
# bppvalue:((optional), float or array) – 基于卡方分布下的Box-Pierce检验的p统计量
from statsmodels.stats.diagnostic import acorr_ljungbox
df = acorr_ljungbox(data_diff,lags=[5,10,15,20],return_df=True)
df
lb_stat | lb_pvalue | |
---|---|---|
5 | 93.602800 | 1.174913e-18 |
10 | 174.501188 | 3.240017e-32 |
15 | 409.920335 | 5.682954e-78 |
20 | 512.419605 | 7.287220e-96 |
可以看到P_values很小,因此拒绝原假设,认为此序列不是白噪声序列
Q检验
df = acorr_ljungbox(data_diff,lags=[5,10,15,20],boxpierce=True,return_df=True)
df
lb_stat | lb_pvalue | bp_stat | bp_pvalue | |
---|---|---|---|---|
5 | 93.602800 | 1.174913e-18 | 91.937305 | 2.631583e-18 |
10 | 174.501188 | 3.240017e-32 | 170.358494 | 2.338185e-31 |
15 | 409.920335 | 5.682954e-78 | 395.340945 | 6.587765e-75 |
20 | 512.419605 | 7.287220e-96 | 491.559590 | 1.700107e-91 |
bp_pvalues就是Q检验的P值