library(tseries)
library(aTSA)
# create time series objects
<- ts(rnorm(100), start = c(1990,1), frequency = 12)
ts1 <- ts(rnorm(100), start = c(1995,1), frequency = 12)
ts2 <- ts(rnorm(100), start = c(2000,1), frequency = 12)
ts3
# create list of time series
<- list(ts1, ts2, ts3) ts_list
Introduction
A time series is a set of data points collected at regular intervals of time. Sometimes, the data points in a time series change over time in a predictable way. This is called a stationary time series. Other times, the data points change in an unpredictable way. This is called a non-stationary time series.
Imagine you are playing a game of catch with a friend. If you throw the ball back and forth at the same speed and distance, that’s like a stationary time series. But if you keep throwing the ball harder and farther, that’s like a non-stationary time series.
There are two tests that we can use to see if a time series is stationary or non-stationary. The first test is called the ADF test, which stands for Augmented Dickey-Fuller test. The second test is called the Phillips-Perron test.
The ADF test looks at the data points and checks to see if the average value of the data points is the same over time. If the average value is the same, then the time series is stationary. If the average value is not the same, then the time series is non-stationary.
The Phillips-Perron test is similar to the ADF test, but it is a bit more advanced. It checks to see if the data points are changing in a predictable way. If the data points are changing in a predictable way, then the time series is stationary. If the data points are changing in an unpredictable way, then the time series is non-stationary.
So, in short, The ADF test checks if the mean of the time series is constant over time and Phillips-Perron test checks if the variance of the time series is constant over time.
Now, you can use these two tests to see if the time series you are studying is stationary or non-stationary, just like how you can use the game of catch to see if your throws are the same or different.
Function
To perform these test we can use two libraries, one is the {tseries}
library for the adf.test()
and the other is the {aTSA}
for the pp.test()
Let’s see some examples.
Examples
Let’s first make our time series obejcts and place them in a list.
Now let’s make our functions.
# function to test for stationarity
<- function(x) {
adf_is_stationary adf.test(x)$p.value > 0.05
}
<- function(x) {
pp_is_stationary <- pp.test(x) |> as.data.frame()
pp_df $p.value > 0.05
pp_df }
Time to use lapply()
!
# apply function to each time series in list
lapply(ts_list, adf_is_stationary)
Augmented Dickey-Fuller Test
alternative: stationary
Type 1: no drift no trend
lag ADF p.value
[1,] 0 -10.97 0.01
[2,] 1 -7.70 0.01
[3,] 2 -5.23 0.01
[4,] 3 -4.05 0.01
[5,] 4 -4.03 0.01
Type 2: with drift no trend
lag ADF p.value
[1,] 0 -11.48 0.01
[2,] 1 -8.32 0.01
[3,] 2 -5.81 0.01
[4,] 3 -4.59 0.01
[5,] 4 -4.63 0.01
Type 3: with drift and trend
lag ADF p.value
[1,] 0 -11.42 0.01
[2,] 1 -8.28 0.01
[3,] 2 -5.77 0.01
[4,] 3 -4.56 0.01
[5,] 4 -4.59 0.01
----
Note: in fact, p.value = 0.01 means p.value <= 0.01
Augmented Dickey-Fuller Test
alternative: stationary
Type 1: no drift no trend
lag ADF p.value
[1,] 0 -10.60 0.01
[2,] 1 -7.88 0.01
[3,] 2 -5.96 0.01
[4,] 3 -5.26 0.01
[5,] 4 -4.90 0.01
Type 2: with drift no trend
lag ADF p.value
[1,] 0 -10.64 0.01
[2,] 1 -7.98 0.01
[3,] 2 -6.08 0.01
[4,] 3 -5.41 0.01
[5,] 4 -5.08 0.01
Type 3: with drift and trend
lag ADF p.value
[1,] 0 -10.58 0.01
[2,] 1 -7.94 0.01
[3,] 2 -6.06 0.01
[4,] 3 -5.39 0.01
[5,] 4 -5.07 0.01
----
Note: in fact, p.value = 0.01 means p.value <= 0.01
Augmented Dickey-Fuller Test
alternative: stationary
Type 1: no drift no trend
lag ADF p.value
[1,] 0 -9.19 0.01
[2,] 1 -6.65 0.01
[3,] 2 -5.41 0.01
[4,] 3 -5.33 0.01
[5,] 4 -4.77 0.01
Type 2: with drift no trend
lag ADF p.value
[1,] 0 -9.14 0.01
[2,] 1 -6.62 0.01
[3,] 2 -5.39 0.01
[4,] 3 -5.30 0.01
[5,] 4 -4.75 0.01
Type 3: with drift and trend
lag ADF p.value
[1,] 0 -9.11 0.01
[2,] 1 -6.59 0.01
[3,] 2 -5.36 0.01
[4,] 3 -5.29 0.01
[5,] 4 -4.73 0.01
----
Note: in fact, p.value = 0.01 means p.value <= 0.01
[[1]]
logical(0)
[[2]]
logical(0)
[[3]]
logical(0)
lapply(ts_list, pp_is_stationary)
Phillips-Perron Unit Root Test
alternative: stationary
Type 1: no drift no trend
lag Z_rho p.value
3 -111 0.01
-----
Type 2: with drift no trend
lag Z_rho p.value
3 -110 0.01
-----
Type 3: with drift and trend
lag Z_rho p.value
3 -110 0.01
---------------
Note: p-value = 0.01 means p.value <= 0.01
Phillips-Perron Unit Root Test
alternative: stationary
Type 1: no drift no trend
lag Z_rho p.value
3 -101 0.01
-----
Type 2: with drift no trend
lag Z_rho p.value
3 -101 0.01
-----
Type 3: with drift and trend
lag Z_rho p.value
3 -101 0.01
---------------
Note: p-value = 0.01 means p.value <= 0.01
Phillips-Perron Unit Root Test
alternative: stationary
Type 1: no drift no trend
lag Z_rho p.value
3 -92.9 0.01
-----
Type 2: with drift no trend
lag Z_rho p.value
3 -92.9 0.01
-----
Type 3: with drift and trend
lag Z_rho p.value
3 -93 0.01
---------------
Note: p-value = 0.01 means p.value <= 0.01
[[1]]
[1] FALSE FALSE FALSE
[[2]]
[1] FALSE FALSE FALSE
[[3]]
[1] FALSE FALSE FALSE
Voila!