# ADF and Phillips-Perron Tests for Stationarity using lists

**Steve's Data Tips and Tricks**, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

# 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.

library(tseries) library(aTSA) # create time series objects ts1 <- ts(rnorm(100), start = c(1990,1), frequency = 12) ts2 <- ts(rnorm(100), start = c(1995,1), frequency = 12) ts3 <- ts(rnorm(100), start = c(2000,1), frequency = 12) # create list of time series ts_list <- list(ts1, ts2, ts3)

Now let’s make our functions.

# function to test for stationarity adf_is_stationary <- function(x) { adf.test(x)$p.value > 0.05 } pp_is_stationary <- function(x) { pp_df <- pp.test(x) |> as.data.frame() pp_df$p.value > 0.05 }

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!

**leave a comment**for the author, please follow the link and comment on their blog:

**Steve's Data Tips and Tricks**.

R-bloggers.com offers

**daily e-mail updates**about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.