Tests for trends in time series"

knitr::opts_chunk$set(collapse = TRUE, comment = "#")
library(funtimes)
# devtools::load_all(".") #remove this line

Introduction

The majority of studies focus on detection of linear or monotonic trends, using

typically under the assumption of uncorrelated data.

There exist two main problems:

These problems can be addressed by using tests for non-monotonic trends assuming that observations can be autocorrelated.

set.seed(777)
n <- 100
Time <- c(1:n)
X0 <- arima.sim(list(order = c(1, 0, 0), ar = 0.5), n = n, n.start = 100, sd = 0.5)
X1 <- 2*Time/n + X0
X2 <- 2*(Time/n)^0.5 + X0
X3 <- 0.5*(Time - n/2)/n - 6*((Time - n/2)/n)^2 + X0
X <- as.data.frame(cbind(X0, X1, X2, X3))
library(ggplot2)
library(patchwork)
p1 <- ggplot(X, aes(x = Time, y = X1)) + geom_line() + theme_minimal()
p2 <- ggplot(X, aes(x = Time, y = X2)) + geom_line() + theme_minimal()
p3 <- ggplot(X, aes(x = Time, y = X3)) + geom_line() + theme_minimal()

p1 + p2 + p3 + 
  plot_annotation(
    title = 'Time series simulated for different alternative hypotheses',
    tag_levels = 'A'
  )

The time series above were simulated:
A) X1 with linear trend,
B) X2 with square root -- nonlinear monotonic -- trend, and
C) X3 with quadratic -- nonlinear non-monotonic -- trend,
with stationary autocorrelated innovations X0: $X0_t = 0.5X0_{t-1} + e_t$, where $e_t \sim N(0, 0.5^2)$.

ggplot(X, aes(x = Time, y = X0)) + geom_line() + theme_minimal()

Let's test these time series using the functions from package funtimes, using significance level $\alpha = 0.05$.

To install and load the package, run

install.packages("funtimes")
library(funtimes)

Testing for presence of a trend

Function notrend_test tests the null hypothesis of no trend against different alternatives defined by the corresponding tests.

Linear trend

Consider the following pair of hypotheses
$H_0$: no trend
$H_1$: linear trend
that can be tested specifically using t-test.

Assuming the time series may be autocorrelated (which is the usual case with observational data), we apply sieve-bootstrap version of the t-test, by adapting the approach of @Noguchi_etal_2011:

notrend_test(X0)

The large $p$-value correctly indicates that there is not enough evidence to reject the hypothesis of no trend in X0 in favor of the alternative hypothesis of a linear trend.

For the other time series, $p$-values are reported below:

apply(X[,-1], 2, function(x) notrend_test(x)$p.value)

indicating that the null hypothesis of no trend could be rejected and hypothesis of a linear trend could be accepted for X1 and X2. While X3 has a trend (based on the way it was simulated and the time series plot above), the alternative hypothesis of a linear trend does not fit in this case, so the test for linear trend (t-test) failed to reject the null hypothesis.

Monotonic trend

Since a linear trend is also a monotonic trend, we may expect seeing similar results when testing the following pair of hypotheses
$H_0$: no trend
$H_1$: monotonic trend
using Mann--Kendall test.

Apply Mann--Kendall test, also with the sieve-bootstrap enhancement for potentially autocorrelated data; $p$-values are shown below:

apply(X, 2, function(x) notrend_test(x, test = "MK")$p.value)

indicating that the null hypothesis of no trend could be rejected and hypothesis of a monotonic trend could be accepted for X1 and X2. For X0 and X3, the null hypothesis could not be rejected, because X0 does not have a trend, and X3 has a trend that does not match the alternative hypothesis.

Any trend

If the interest is in testing for any, potentially non-monotonic trend, consider testing the following pair of hypotheses
$H_0$: no trend
$H_1$: any trend
using local regression-based WAVK test [@Wang_etal_2008].

Apply WAVK test, also with the sieve-bootstrap enhancement for potentially autocorrelated data:

apply(X, 2, function(x) notrend_test(x, test = "WAVK", 
                                     factor.length = "adaptive.selection")$p.value)

The results indicate that WAVK test was correct in non-rejecting the null hypothesis for X0, and correctly rejected it for the time series with trends X1, X2, and X3.

@Lyubchich_etal_2013_wavk originally implemented hybrid bootstrap to this test statistic, available from the wavk_test function described in the next section.

Testing a specific parametric form of trend

Function wavk_test is developed for the following goodness-of-fit question [@Lyubchich_etal_2013_wavk]:
$H_0$: trend is of form $f(\theta,t)$
$H_1$: trend is not of form $f(\theta,t)$
where $f$ belongs to a known family of smooth parametric functions, and $\theta$ are its parameters.

Note Considering $f(\theta,t)$ being some polynomial function, non-rejection of the null hypothesis means that function $f(\theta,t)$ or its simpler form (lower-order polynomial) is sufficient for describing the trend in the tested time series.

Note The case of $f(\theta,t) \equiv 0$ corresponds to testing for no trend (in other words, for a constant trend, same as in the previous section), and the following code differs only in the type of bootstrap used,

notrend_test(X0, test = "WAVK", factor.length = "adaptive.selection") # WAVK with sieve bootstrap
wavk_test(X0 ~ 0, factor.length = "adaptive.selection") # WAVK with hybrid bootstrap

To test a linear trend $f(\theta,t) = \theta_0 + \theta_1 t$, use

wavk_test(X0 ~ t, factor.length = "adaptive.selection")

Note that the time sequence t is specified automatically within the function.

For the other time series, $p$-values are shown below:

apply(X[,-1], 2, function(x) wavk_test(x ~ t, factor.length = "adaptive.selection")$p.value)

The function poly could also be used, for example, test quadratic trend $f(\theta,t) = \theta_0 + \theta_1 t + \theta_2 t^2$ and show the trend estimates using the argument out = TRUE:

wavk_test(X3 ~ poly(t, 2), factor.length = "adaptive.selection", out = TRUE)

Citation {-}

This vignette belongs to R package funtimes. If you wish to cite this page, please cite the package:

citation("funtimes")

References



Try the funtimes package in your browser

Any scripts or data that you put into this service are public.

funtimes documentation built on March 31, 2023, 7:35 p.m.