I'm experiencing an issue in which it seems forecast::auto.arima() isn't returning a model with a differencing parameter when it should. Read through my reproducible example to arrive at the question.
I have the following data:
library(magrittr)
library(dplyr)
mydata <- c(305, 348, 337, 350, 368, 345, 370, 291, 337, 323, 328, 307,
299, 323, 292, 273, 282, 333, 325, 322, 298, 306, 339, 320,
348, 349, 381, 331, 373, 349, 307, 321, 347, 304, 314, 273,
309, 300, 266, 280, 318, 346, 399, 360, 394, 447, 420, 417,
341, 320, 292, 264, 264, 276, 292, 284, 219, 252)
Which I then convert to a univariate time series object (and clean):
global_ts <- ts(data=mydata, start=1960, end=2017, frequency=1) %>%
forecast::tsclean(.)
The data look like this:
ggplot2::autoplot(global_ts) +
ggplot2::theme_bw() +
ggplot2::geom_line(size=0.6) +
ggplot2::geom_point(shape = 21, colour = "black", fill = "dodgerblue", size = 3, stroke = 1) +
ggplot2::labs(x="\nTime [years]") +
ggplot2::theme(axis.text.x = ggplot2::element_text(size=12)) +
ggplot2::theme(axis.text.y = ggplot2::element_text(size=12)) +
ggplot2::theme(axis.title.x = ggplot2::element_text(size=18)) +
ggplot2::theme(axis.title.y = ggplot2::element_text(size=18))
These data are not stationary:
tseries::adf.test(global_ts)
The data show autocorrelation:
acf(global_ts, lag.max = 20)
The data show partial autocorrelation:
To stationarize the data, I decided to calculate the first difference:
global_ts_difference_lag_1 = diff(global_ts, differences = 1)
The first differences look like this:
ggplot2::autoplot(global_ts_difference_lag_1) +
ggplot2::theme_bw() +
ggplot2::geom_line(size=0.6) +
ggplot2::geom_point(shape = 21, colour = "black", fill = "dodgerblue", size = 3, stroke = 1) +
ggplot2::labs(x="\nTime [years]") +
ggplot2::theme(axis.text.x = ggplot2::element_text(size=12)) +
ggplot2::theme(axis.text.y = ggplot2::element_text(size=12)) +
ggplot2::theme(axis.title.x = ggplot2::element_text(size=18)) +
ggplot2::theme(axis.title.y = ggplot2::element_text(size=18))
The first order differenced data is stationary:
tseries::adf.test(global_ts_difference_lag_1)
The first order differenced data show no autocorrelation:
acf(global_ts_difference_lag_1, lag.max = 20)
The first order differenced data show no partial autocorrelation (note: it's acceptable to have one line eclipse the 95% confidence intervals because 19/20 = 0.95):
pacf(global_ts_difference_lag_1, lag.max = 20)
I performed an ARIMA using forecast::auto.arima():
forecast::auto.arima(global_ts, ic="aic", trace=TRUE, stepwise = FALSE)
The forecast::auto.arima() function returned a non-differenced ARIMA, even though the data are clearly non-stationary without differencing...
If I forecast using ARIMA(1,0,0), I get the following:
global_arima <- arima(global_ts, order=c(1,0,0), include.mean = TRUE)
global_arima
plot(forecast::forecast(global_arima, h=11, level=95))
NOW, If I specify first order differencing as an argument in the forecast::auto.arima() function, it returns a different model:
forecast::auto.arima(global_ts, ic="aic", d=1, trace=TRUE, stepwise = FALSE)
If I forecast using ARIMA(1,1,0), I get the following:
global_arima <- arima(global_ts, order=c(1,1,0), include.mean = TRUE)
global_arima
plot(forecast::forecast(global_arima, h=11, level=95))
MY QUESTION IS THE FOLLOWING -
Why isn't forecast::auto.arima() correctly performing a check for differencing?
The documentation for forecast::auto.arima() says the 'd' argument is the "order of first-differencing. If missing, will choose a value based on KPSS test."
Is forecast::auto.arima() actually choosing a value for differencing (d) based on the KPSS test? It seems to not actually be doing this...
To cover my bases, I performed a manual KPSS test, which resulted in clear non-stationarity for the original time series:
tseries::kpss.test(global_ts)
What gives? Am I missing something? Which forecast should I trust?
Oh and I should also mention that I get strange results when using forecast::ndiffs(), which is supposed to tell the user the number of differences are required to achieve stationarity. The test performed seems to dictate the outcome...
forecast::ndiffs(global_ts, test="kpss")
forecast::ndiffs(global_ts, test="adf")
forecast::ndiffs(global_ts, test="pp")
Why would these tests give such wildly different results? Further, why would tseries::kpss.test() give different results than forecast::ndiffs()??