使用R的时间序列的STL趋势


27

我是R和时间序列分析的新手。我试图找到较长的(40年)每日温度时间序列的趋势,并尝试采用不同的近似值。第一个只是简单的线性回归,第二个是Loess的时间序列的季节性分解。

在后者看来,季节性成分大于趋势。但是,如何量化趋势?我只想说一说这个趋势有多强。

     Call:  stl(x = tsdata, s.window = "periodic")
     Time.series components:
        seasonal                trend            remainder               
Min.   :-8.482470191   Min.   :20.76670   Min.   :-11.863290365      
1st Qu.:-5.799037090   1st Qu.:22.17939   1st Qu.: -1.661246674 
Median :-0.756729578   Median :22.56694   Median :  0.026579468      
Mean   :-0.005442784   Mean   :22.53063   Mean   : -0.003716813 
3rd Qu.:5.695720249    3rd Qu.:22.91756   3rd Qu.:  1.700826647    
Max.   :9.919315613    Max.   :24.98834   Max.   : 12.305103891   

 IQR:
         STL.seasonal STL.trend STL.remainder data   
         11.4948       0.7382    3.3621       10.8051
       % 106.4          6.8      31.1         100.0  
     Weights: all == 1
     Other components: List of 5   
$ win  : Named num [1:3] 153411 549 365  
$ deg  : Named int [1:3] 0 1 1   
$ jump : Named num [1:3] 15342 55 37  
$ inner: int 2  
$ outer: int 0

在此处输入图片说明

Answers:


20

我不会为此而烦恼stl()-用于提取趋势的最低平滑器的带宽非常小,导致您看到的小范围波动。我将使用加法模型。这是一个使用西蒙·伍德(Simon Wood)关于GAM的书中的数据和模型代码的示例:

require(mgcv)
require(gamair)
data(cairo)
cairo2 <- within(cairo, Date <- as.Date(paste(year, month, day.of.month, 
                                              sep = "-")))
plot(temp ~ Date, data = cairo2, type = "l")

开罗温度数据

用趋势和季节成分拟合模型--- 警告这很慢:

mod <- gamm(temp ~ s(day.of.year, bs = "cc") + s(time, bs = "cr"),
            data = cairo2, method = "REML",
            correlation = corAR1(form = ~ 1 | year),
            knots = list(day.of.year = c(0, 366)))

拟合的模型如下所示:

> summary(mod$gam)

Family: gaussian 
Link function: identity 

Formula:
temp ~ s(day.of.year, bs = "cc") + s(time, bs = "cr")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  71.6603     0.1523   470.7   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Approximate significance of smooth terms:
                 edf Ref.df       F p-value    
s(day.of.year) 7.092  7.092 555.407 < 2e-16 ***
s(time)        1.383  1.383   7.035 0.00345 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

R-sq.(adj) =  0.848  Scale est. = 16.572    n = 3780

我们可以通过以下方式可视化趋势和季节性条件

plot(mod$gam, pages = 1)

开罗拟合趋势和季节性

如果要在观察到的数据上绘制趋势,可以通过以下方法进行预测:

pred <- predict(mod$gam, newdata = cairo2, type = "terms")
ptemp <- attr(pred, "constant") + pred[,2]
plot(temp ~ Date, data = cairo2, type = "l",
     xlab = "year",
     ylab = expression(Temperature ~ (degree*F)))
lines(ptemp ~ Date, data = cairo2, col = "red", lwd = 2)

开罗拟合趋势

或与实际模型相同:

pred2 <- predict(mod$gam, newdata = cairo2)
plot(temp ~ Date, data = cairo2, type = "l",
     xlab = "year",
     ylab = expression(Temperature ~ (degree*F)))
lines(pred2 ~ Date, data = cairo2, col = "red", lwd = 2)

开罗拟合模型

这只是一个例子,可能需要进行更深入的分析,以解决缺少一些数据这一事实,但是以上所述应该是一个很好的起点。

关于您如何量化趋势的观点-这是一个问题,因为趋势不是线性的,无论您的stl()版本还是我展示的GAM版本都没有。如果是这样,您可以给出变化率(斜率)。如果您想知道估计的趋势在采样期间发生了多少变化,那么我们可以使用其中包含的数据pred并仅计算趋势组件中序列的开始和结束之间的差值:

> tail(pred[,2], 1) - head(pred[,2], 1)
    3794 
1.756163

因此平均温度比记录开始时高1.76度。


查看图表,我认为华氏温度和摄氏温度可能会有些混淆。
亨利

很好发现-我已经做了类似的事情几个月了,数据以摄氏度为单位。是习惯吗?
恢复莫妮卡-G.辛普森

感谢Gavin,这是一个非常不错且可以理解的答案。我会尝试您的建议。绘制stl()趋势分量并进行线性回归是个好主意吗?
pacomet 2011年

1
@pacomet-不,不是真的,除非像我上面那样适合拟合残差中自相关的模型。您可以为此使用GLS(gls()在nlme包中)。但是,正如上面针对开罗显示的那样,并且STL对您的数据提出了建议,这种趋势不是线性的。因此,线性趋势将不合适-因为它无法正确描述数据。您需要对数据进行尝试,但如果最适合数据,则如我所示的AM会退化为线性趋势。
恢复莫妮卡-G.辛普森

1
@ andreas-h我不会那样做;STL趋势已过拟合。使GAM适应AR()结构并解释趋势。这将提供适当的回归模型,这对您将更有用。
恢复莫妮卡-辛普森(G. Simpson)

4

Gavin提供了一个非常彻底的答案,但是对于更简单,更快速的解决方案,我建议将stl函数t.window参数设置为一个值,该值是ts数据频率的倍数。我将使用推断出的兴趣周期(例如,具有日分辨率数据的年代际趋势值3660)。您可能也对作者的论文中描述的stl2软件包感兴趣。我已经将Gavin的方法应用于我自己的数据,它也非常有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.