forked from robjhyndman/fpp3_slides
/
3-6-stl.Rmd
134 lines (113 loc) · 3.81 KB
/
3-6-stl.Rmd
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
---
title: "3. Time series decomposition"
author: "3.6 STL decomposition"
date: "OTexts.org/fpp3/"
classoption: aspectratio=169
titlepage: fpp3title.png
titlecolor: fpp3red
toc: false
output:
binb::monash:
colortheme: monashwhite
fig_width: 7.5
fig_height: 3
keep_tex: no
includes:
in_header: fpp3header.tex
---
```{r setup, include=FALSE}
source("setup.R")
library(gganimate)
```
## STL decomposition
\fontsize{13}{14}\sf
* STL: "Seasonal and Trend decomposition using Loess"
* Very versatile and robust.
* Unlike X-12-ARIMA, STL will handle any type of seasonality.
* Seasonal component allowed to change over time, and rate of change controlled by user.
* Smoothness of trend-cycle also controlled by user.
* Robust to outliers
* Not trading day or calendar adjustments.
* Only additive.
* Take logs to get multiplicative decomposition.
* Use Box-Cox transformations to get other decompositions.
## STL decomposition
```{r usretail, include=FALSE}
us_retail_employment <- us_employment |>
filter(year(Month) >= 1990, Title == "Retail Trade") |>
select(-Series_ID)
us_retail_employment
```
```{r stlwindow9, warning=FALSE, fig.width=8.5, fig.height=3.4}
us_retail_employment |>
model(STL(Employed ~ season(window = 9), robust = TRUE)) |>
components() |>
autoplot() + labs(title = "STL decomposition: US retail employment")
```
## STL decomposition
```{r stlwindowanim, echo=FALSE, warning=FALSE, message=FALSE, fig.show='animate', interval=1/10, fig.height=5.35, fig.width=8, aniopts='controls,buttonsize=0.3cm,width=11.5cm', eval=TRUE}
s_windows <- seq(5, 55, by = 2)
stl_defs <- purrr::map(s_windows, function(s_window) {
STL(Employed ~ season(window = s_window), robust = TRUE)
})
names(stl_defs) <- sprintf("season(window=%02d)", s_windows)
us_retail_employment |>
model(!!!stl_defs) |>
components() |>
as_tibble() |>
pivot_longer(Employed:remainder,
names_to = "component", names_ptypes = list(component = factor(levels = c("Employed", "trend", "season_year", "remainder"))),
values_to = "Employed"
) |>
ggplot(aes(x = Month, y = Employed)) +
geom_line() +
facet_grid(rows = vars(component), scales = "free_y") +
labs(
title = "STL decomposition of US retail employment",
subtitle = "{closest_state}"
) +
transition_states(.model, wrap=FALSE)
```
\vspace*{10cm}
## STL decomposition
```{r echo = TRUE, results = 'hide'}
us_retail_employment |>
model(STL(Employed ~ season(window = 5))) |>
components()
us_retail_employment |>
model(STL(
Employed ~ trend(window = 15) +
season(window = "periodic"),
robust = TRUE
)) |>
components()
```
\fontsize{12}{13}\sf
* `trend(window = ?)` controls wiggliness of trend component.
* `season(window = ?)` controls variation on seasonal component.
* `season(window = 'periodic')` is equivalent to an infinite window.
## STL decomposition
```{r mstl, fig.width=8.5, fig.height=3.4}
us_retail_employment |>
model(STL(Employed)) |>
components() |>
autoplot()
```
\only<2>{\begin{textblock}{7}(8,0.2)\fontsize{11}{11}\sf
\begin{alertblock}{}
\begin{itemize}\tightlist
\item \texttt{STL()} chooses \texttt{season(window=13)} by default
\item Can include transformations.
\end{itemize}
\end{alertblock}
\end{textblock}}
## STL decomposition
\fontsize{13}{14.5}\sf
* Algorithm that updates trend and seasonal components iteratively.
* Starts with $\hat{T}_t=0$
* Uses a mixture of loess and moving averages to successively refine the trend and seasonal estimates.
* The trend window controls loess bandwidth applied to deasonalised values.
* The season window controls loess bandwidth applied to detrended subseries.
* Robustness weights based on remainder.
* Default season: `window = 13`
* Default trend:\mbox{}\hfill\hbox{\texttt{window = nextodd(ceiling((1.5*period)/(1-(1.5/s.window)))}}