作者:黄天元,复旦大学博士在读,热爱数据科学与开源工具(R),致力于利用数据科学迅速积累行业经验优势和科学知识发现,涉猎内容包括但不限于信息计量、机器学习、数据可视化、应用统计建模、知识图谱等,著有《R语言数据高效处理指南》(《R语言数据高效处理指南》(黄天元)【摘要 书评 试读】- 京东图书,《R语言数据高效处理指南》(黄天元)【简介_书评_在线阅读】 - 当当图书)。知乎专栏:R语言数据挖掘。邮箱:huang.tian-yuan@qq.com.欢迎合作交流。
一般来说,时间序列能够分解为趋势性、周期性和残差三个部分。传统的分解方法可以划分为可加性分解(additive)和可乘性分解(multiplicative)两种,算法可见6.3 Classical decomposition | Forecasting: Principles and Practice。其中,可加性的分解目前不建议使用,原因是:
1、分解的时候,趋势性的预测总是缺乏首尾的数值。这一点做滑动平均(moving average)就会有体会,用前n个序列的均值来作为n+1时刻的趋势预测,那么前面n个数值注定都是缺失值,而最后n个数值也无法获得;
2、对于骤增和骤降不敏感,显得过于平滑,因此如果有突发的事件也难以进行捕捉;
3、对季节性的预测非常刻板,基本假设中周期性是固定的,如果随着时间改变其周期性波动也发生改变,可加性分解就无法捕捉到。
简单方法的R实现函数为decompose(type="multiplicative"),type可以改为additive,自由选择分解的方法。
后来针对简单方法的不足,提出了X11分解法和SEATS分解法,以及STL分解法,下面分别介绍。
X11X11分解法的特点我们引用6.4 X11 decomposition | Forecasting: Principles and Practice中的原话:“In particular, trend-cycle estimates are available for all observations including the end points, and the seasonal component is allowed to vary slowly over time. X11 also has some sophisticated methods for handling trading day variation, holiday effects and the effects of known predictors. It handles both additive and multiplicative decomposition. The process is entirely automatic and tends to be highly robust to outliers and level shifts in the time series.”也就是说,首尾的数值都能补全,季节因子也能够随着时间变化而发生缓慢变化,能够处理节假日等突发事件,既能够用可加模式也能够用可乘模式,分解过程全自动化而且非常稳健不怕离群值。
在R中,要实现这种分解,需要加载seasonal包,然后调用seas函数,记得设置参数X11 = ""。随便举个例子:
library(seasonal)
library(fpp2)
elecequip %>% seas(x11="") -> fit
autoplot(fit) +
ggtitle("X11 decomposition of electrical equipment index")
SEATS
SEATS是Seasonal Extraction in ARIMA Time Series的缩写,就是从ARIMA模型中提取季节变化因素。它具有一定的限制,就是只能够对季节尺度和月尺度的时间序列进行处理,其他则不行。但是方法究竟有何妙处还没有具体深入,大家可以看原始介绍(http://www.seasonal.website/seasonal.html)。实现也与X11大同小异,是seas函数的默认设置参数,因此直接用seas函数即可分解:
library(seasonal)
elecequip %>% seas() %>%
autoplot() +
ggtitle("SEATS decomposition of electrical equipment index")
STL
STL全称为Seasonal and Trend decomposition using Loess,也就是对季节因子和趋势因子都进行了局部多项式回归的方法。它比以上提到的所有方法都要优秀,因为:
1、SEATS和X11只能解决季节和月尺度的时间序列,STL没有任何限制;
2、季节因子可以随时间变化而变化,变化速率可以用户自定义;
3、趋势因子可以用户自定义;
4、对离群值不敏感,不过这样可能会让局部残差变大。
也有缺点,如只能进行可加性分解,无法根据交易日进行调整。不过如果要用可乘性的分解,其实可以先将序列进行对数化运算,然后再做STL,最后再反推回去即可。一个简单的例子:
elecequip %>% stl(t.window=13, s.window="periodic", robust=TRUE) %>% autoplot()
s.window和t.window分别控制季节和趋势的窗口大小。mstl函数提供了一种懒人模式,把s.window设置为13,并自动设置了t.window的大小。但是在具体问题中,参数的调整往往需要经验,还要具体问题具体分析。
最后介绍几个函数:
seasonal-提取季节因子
trendcycle-提取趋势因子
remainder-提取残差
seasadj-提取季节矫正序列(即剔除季节因子之后的序列)
懒人模式:
A short-cut approach is to use thestlf()function. The following code will decompose the time series using STL, forecast the seasonally adjusted series, and return the reseasonalised forecasts.
fcast <- stlf(elecequip, method='naive') fcast %>% autoplot()
STL分解,自动设置参数,对季节调整序列进行预测,然后再加上季节因子变成最终预测。
自动化一时爽,一直自动化一直爽。但是在需要的时候要随时能够拆了黑盒进行调整和矫正,才能够在合适的时候使用合适的方法,并合理地对结果进行解释。在实践中要做的还有很多。



