Tidy time series analysis and forecasting
Modelling and forecasting
10th June 2024 @ UseR! 2024
Many forecasts are catastrophically wrong, and better described as ‘hopecasting’.
Something is easier to forecast if…
Statistically! (or computationally!)
Consider possible futures for this series:
Good forecasts…
Good forecasts aren’t necessarily accurate!
Usually accuracy is important, but not always.
Forecasts (usually) assume that interventions won’t occur, e.g. COVID-19 measures.
Your turn
How would you forecast visitors to Australia?
Hint: Consider the patterns seen in the data, and how statistics/code can mimic the trend, seasonality, etc.
The naive model
Simply use the most recent observation.
The seasonal naive model
Use the most recent ‘seasonal’ observation.
The naive with drift model
Extrapolate a line between the first and last observation.
The seasonal naive with drift model
Extrapolate between first and last with seasonality.
Models are estimated using model()
:
pbs_scripts |>
model(
NAIVE(Scripts),
SNAIVE(Scripts),
NAIVE(Scripts ~ drift()),
SNAIVE(Scripts ~ drift()),
)
# A mable: 1 x 4
`NAIVE(Scripts)` `SNAIVE(Scripts)` `NAIVE(Scripts ~ drift())`
<model> <model> <model>
1 <NAIVE> <SNAIVE> <RW w/ drift>
# ℹ 1 more variable: `SNAIVE(Scripts ~ drift())` <model>
The mable
A mable (model table) contains 1 row per time series, and 1 column for each specified model.
Forecasts are made using forecast()
:
pbs_scripts <- PBS |>
summarise(Scripts = sum(Scripts))
pbs_scripts |>
model(
NAIVE(Scripts),
SNAIVE(Scripts),
NAIVE(Scripts ~ drift()),
SNAIVE(Scripts ~ drift()),
) |>
forecast(h = "2 years")
# A fable: 96 x 4 [1M]
# Key: .model [4]
.model Month Scripts .mean
<chr> <mth> <dist> <dbl>
1 NAIVE(Scripts) 2008 Jul N(1.2e+07, 2.2e+12) 12123769
2 NAIVE(Scripts) 2008 Aug N(1.2e+07, 4.4e+12) 12123769
3 NAIVE(Scripts) 2008 Sep N(1.2e+07, 6.6e+12) 12123769
4 NAIVE(Scripts) 2008 Oct N(1.2e+07, 8.8e+12) 12123769
5 NAIVE(Scripts) 2008 Nov N(1.2e+07, 1.1e+13) 12123769
6 NAIVE(Scripts) 2008 Dec N(1.2e+07, 1.3e+13) 12123769
7 NAIVE(Scripts) 2009 Jan N(1.2e+07, 1.5e+13) 12123769
8 NAIVE(Scripts) 2009 Feb N(1.2e+07, 1.8e+13) 12123769
9 NAIVE(Scripts) 2009 Mar N(1.2e+07, 2e+13) 12123769
10 NAIVE(Scripts) 2009 Apr N(1.2e+07, 2.2e+13) 12123769
# ℹ 86 more rows
# A fable: 96 x 4 [1M]
# Key: .model [4]
.model Month Scripts .mean
<chr> <mth> <dist> <dbl>
1 NAIVE(Scripts) 2008 Jul N(1.2e+07, 2.2e+12) 12123769
2 NAIVE(Scripts) 2008 Aug N(1.2e+07, 4.4e+12) 12123769
3 NAIVE(Scripts) 2008 Sep N(1.2e+07, 6.6e+12) 12123769
4 NAIVE(Scripts) 2008 Oct N(1.2e+07, 8.8e+12) 12123769
5 NAIVE(Scripts) 2008 Nov N(1.2e+07, 1.1e+13) 12123769
6 NAIVE(Scripts) 2008 Dec N(1.2e+07, 1.3e+13) 12123769
7 NAIVE(Scripts) 2009 Jan N(1.2e+07, 1.5e+13) 12123769
8 NAIVE(Scripts) 2009 Feb N(1.2e+07, 1.8e+13) 12123769
9 NAIVE(Scripts) 2009 Mar N(1.2e+07, 2e+13) 12123769
10 NAIVE(Scripts) 2009 Apr N(1.2e+07, 2.2e+13) 12123769
# ℹ 86 more rows
The fable
A fable (forecast table) is like a tsibble, but with distributions for the forecasted variable.
Exercise 6
Specify appropriate model(s) for the total number of tourists arriving in Victoria.
Estimate them with model()
and produce forecasts for the next 5 years with forecast()
.
Plot the forecasts, and visually evaluate their suitability.
Regression can also forecast, use time as regressors for the response variable.
\[y_t = \beta_0 + \beta_1 t + \sum_{i=1}^m \beta_{s_i} s_{it} + \varepsilon_t\]
Specifying time series linear models
TSLM(y ~ trend() + season())
Specifying time series linear models
TSLM(y ~ trend() + season())
Regression can also incorporate other covariates. For example:
# A mable: 1 x 1
`TSLM(Takings ~ trend() + season() + Occupancy)`
<model>
1 <TSLM>
Difficult to forecast
Forecasting with regressors requires you to forecast the regressors too! Useful regressors are easily known, predictable, or controllable.
Time series patterns often change over time.
The fixed coefficients of regression is unsuitable for most time series.
Exponential smoothing (ETS) is similar to regression, but allows the ‘coefficients’ (states) to vary over time.
\[y_t = \ell_{t-1} + b_{t-1} + s_{t-m} + \varepsilon_t\]
Specifying ETS models
ETS(y ~ error("A") + trend("A") + season("A"))
Exponential smoothing also works for ‘multiplicative’ patterns.
This is where the variation grows proportionately to \(\ell_t\).
For example, multiplicative seasonality:
\[y_t = (\ell_{t-1} + b_{t-1})s_{t-m} + \varepsilon_t\]
Specifying ETS models
ETS(y ~ error("A") + trend("A") + season("M"))
The best ETS model can be chosen automatically using AICc.
Simply don’t specify the right side of the formula for automatic selection.
Specifying ETS models
ETS(y)
Exercise 8
Is the seasonality of total Australian accommodation takings from aus_accommodation_total
additive or multiplicative?
Estimate an ETS model for the data, does the automatic ETS model match the patterns you see in a time plot?
Unlike ETS, ARIMA can’t directly handle multiplicative patterns.
This isn’t a problem though, since we have a transformational trick 🪄
\[\log(x \times y) = \log(x) + \log(y)\]
Before we can use ARIMA, we need to transform our data to be additive.
With the appropriate transformation, we can now estimate an ARIMA model:
Specifying ARIMA models
These will use automatic ARIMA selection (often described as auto.arima()
).
ARIMA(y)
, or ARIMA(log(y))
Other transformations
Multiplicative patterns aren’t always exactly multiplicative - for this we often use power transformations via box_cox(y, lambda)
.
More information: https://otexts.com/fpp3/transformations.html
Exercise 9
Identify if a transformation is necessary for the aus_accommodation_total
Takings
Then estimate an automatically selected ARIMA model for this data.
Compare ARIMA forecasts with the automatic ETS model, how do they differ?
Which model is better?
It depends!
Capturing patterns
Evaluating accuracy
We can determine which model works best on a specific dataset using accuracy evaluation…
Fortunately, that’s up next!
Up next…
Thanks to these Unsplash contributors for their photos