10.2 Regression with ARIMA errors in R

The R function ARIMA() will fit a regression model with ARIMA errors if exogenous regressors are included in the formula. As introduced in Section 9.5, the pdq() special specifies the order of the ARIMA error model. If differencing is specified, then the differencing is applied to all variables in the regression model before the model is estimated. For example, the R command

ARIMA(y ~ x + pdq(1,1,0))

will fit the model \(y_t' = \beta_1 x'_t + \eta'_t\), where \(\eta'_t = \phi_1 \eta'_{t-1} + \varepsilon_t\) is an AR(1) error. This is equivalent to the model \[ y_t = \beta_0 + \beta_1 x_t + \eta_t, \] where \(\eta_t\) is an ARIMA(1,1,0) error. Notice that the constant term disappears due to the differencing. To include a constant in the differenced model, we would add 1 to the model formula.

The ARIMA() function can also be used to select the best ARIMA model for the errors. This is done by not specifying the pdq() special. If differencing is required, then all variables are differenced during the estimation process, although the final model will be expressed in terms of the original variables.

The AICc is calculated for the final model, and this value can be used to determine the best predictors. That is, the procedure should be repeated for all subsets of predictors to be considered, and the model with the lowest AICc value selected.

Example: US Personal Consumption and Income

Figure 10.1 shows the quarterly changes in personal consumption expenditure and personal disposable income from 1970 to 2016 Q3. We would like to forecast changes in expenditure based on changes in income. A change in income does not necessarily translate to an instant change in consumption (e.g., after the loss of a job, it may take a few months for expenses to be reduced to allow for the new circumstances). However, we will ignore this complexity in this example and try to measure the instantaneous effect of the average change of income on the average change of consumption expenditure.

us_change <- readr::read_csv("https://otexts.com/fpp3/extrafiles/us_change.csv") %>%
  mutate(Time = yearquarter(Time)) %>%
  as_tsibble(index = Time)
us_change %>%
  gather("var", "value", Consumption, Income) %>%
  ggplot(aes(x = Time, y = value)) +
  geom_line() +
  facet_grid(vars(var), scales = "free_y") +
  xlab("Year") + ylab(NULL) +
  ggtitle("Quarterly changes in US consumption and personal income")
Percentage changes in quarterly personal consumption expenditure and personal disposable income for the USA, 1970 to 2016 Q3.

Figure 10.1: Percentage changes in quarterly personal consumption expenditure and personal disposable income for the USA, 1970 to 2016 Q3.

fit <- us_change %>%
  model(ARIMA(Consumption ~ Income))
report(fit)
#> Series: Consumption 
#> Model: LM w/ ARIMA(1,0,2) errors 
#> 
#> Coefficients:
#>          ar1      ma1     ma2  Income  intercept
#>       0.6922  -0.5758  0.1984  0.2028     0.5990
#> s.e.  0.1159   0.1301  0.0756  0.0461     0.0884
#> 
#> sigma^2 estimated as 0.3219:  log likelihood=-156.9
#> AIC=325.9   AICc=326.4   BIC=345.3

The data are clearly already stationary (as we are considering percentage changes rather than raw expenditure and income), so there is no need for any differencing. The fitted model is \[\begin{align*} y_t &= 0.599 + 0.203 x_t + \eta_t, \\ \eta_t &= 0.692 \eta_{t-1} + \varepsilon_t -0.576 \varepsilon_{t-1} + 0.198 \varepsilon_{t-2},\\ \varepsilon_t &\sim \text{NID}(0,0.322). \end{align*}\]

We can recover estimates of both the \(\eta_t\) and \(\varepsilon_t\) series using the residuals() function.

bind_rows(
  `Regression Errors` = residuals(fit, type="regression"),
  `ARIMA Errors` = residuals(fit, type="innovation"),
  .id = "type"
) %>%
  ggplot(aes(x = Time, y = .resid)) +
  geom_line() +
  facet_grid(vars(type), scales = "free_y") +
  xlab("Year") + ylab(NULL)
Regression errors ($\eta_t$) and ARIMA errors ($\varepsilon_t$) from the fitted model.

Figure 10.2: Regression errors (\(\eta_t\)) and ARIMA errors (\(\varepsilon_t\)) from the fitted model.

It is the ARIMA errors that should resemble a white noise series.

augment(fit) %>%
  gg_tsdisplay(plot_type = "histogram")
#> Plot variable not specified, automatically selected `y = Consumption`
The residuals (i.e., the ARIMA errors) are not significantly different from white noise.

Figure 10.3: The residuals (i.e., the ARIMA errors) are not significantly different from white noise.

augment(fit) %>%
  features(.resid, ljung_box, dof = 5, lag = 8)
#> # A tibble: 1 x 3
#>   .model                      lb_stat lb_pvalue
#>   <chr>                         <dbl>     <dbl>
#> 1 ARIMA(Consumption ~ Income)    5.89     0.117