## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE, comment = "#>", eval = TRUE, cache = FALSE,
  warning = FALSE, fig.width = 8, fig.height = 5
)

## ----package_installation-----------------------------------------------------
for (
  package in c(
    "ggplot2", "mvtnorm",
    # "bcp",
    "breakfast", "changepoint", "cpm", "ecp", "fpop", "mcp",
    "mosum", "not", "segmented", "stepR", "strucchange", "wbs"
  )
) {
  if (!requireNamespace(package, quietly = TRUE)) utils::install.packages(
    package, repos = "https://cloud.r-project.org", quiet = TRUE
  )
}

## ----data-setup-univariate-mean-change----------------------------------------
set.seed(1)
p <- 1

# Univariate mean change
mean_data_1 <- rbind(
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(100, p)),
  mvtnorm::rmvnorm(400, mean = rep(50, p), sigma = diag(100, p)),
  mvtnorm::rmvnorm(300, mean = rep(2, p), sigma = diag(100, p))
)

plot.ts(mean_data_1)

## ----data-setup-univariate-mean-and-or-variance-change------------------------
# Univariate mean and/or variance change
mv_data_1 <- rbind(
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(400, mean = rep(10, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(50, p)),
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(400, mean = rep(10, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(300, mean = rep(10, p), sigma = diag(50, p))
)

plot.ts(mv_data_1)

## ----data-setup-multivariate-mean-change--------------------------------------
p <- 3

# Multivariate mean change
mean_data_3 <- rbind(
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(100, p)),
  mvtnorm::rmvnorm(400, mean = rep(50, p), sigma = diag(100, p)),
  mvtnorm::rmvnorm(300, mean = rep(2, p), sigma = diag(100, p))
)

plot.ts(mean_data_3)

## ----data-setup-multivariate-mean-and-or-variance-change----------------------
# Multivariate mean and/or variance change
mv_data_3 <- rbind(
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(400, mean = rep(10, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(50, p)),
  mvtnorm::rmvnorm(300, mean = rep(0, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(400, mean = rep(10, p), sigma = diag(1, p)),
  mvtnorm::rmvnorm(300, mean = rep(10, p), sigma = diag(50, p))
)

plot.ts(mv_data_3)

## ----data-setup-linear-regression---------------------------------------------
# Linear regression
n <- 300
p <- 4
x <- mvtnorm::rmvnorm(n, rep(0, p), diag(p))
theta_0 <- rbind(c(1, 3.2, -1, 0), c(-1, -0.5, 2.5, -2), c(0.8, 0, 1, 2))
y <- c(
  x[1:100, ] %*% theta_0[1, ] + rnorm(100, 0, 3),
  x[101:200, ] %*% theta_0[2, ] + rnorm(100, 0, 3),
  x[201:300, ] %*% theta_0[3, ] + rnorm(100, 0, 3)
)
lm_data <- data.frame(y = y, x = x)

plot.ts(lm_data)

## ----data-setup-logistic-regression-------------------------------------------
# Logistic regression
x <- matrix(rnorm(1500, 0, 1), ncol = 5)
theta <- rbind(rnorm(5, 0, 1), rnorm(5, 2, 1))
y <- c(
  rbinom(125, 1, 1 / (1 + exp(-x[1:125, ] %*% theta[1, ]))),
  rbinom(175, 1, 1 / (1 + exp(-x[126:300, ] %*% theta[2, ])))
)
binomial_data <- data.frame(y = y, x = x)

# Poisson regression
n <- 1100
p <- 3
x <- mvtnorm::rmvnorm(n, rep(0, p), diag(p))
delta <- rnorm(p)
theta_0 <- c(1, 0.3, -1)
y <- c(
  rpois(500, exp(x[1:500, ] %*% theta_0)),
  rpois(300, exp(x[501:800, ] %*% (theta_0 + delta))),
  rpois(200, exp(x[801:1000, ] %*% theta_0)),
  rpois(100, exp(x[1001:1100, ] %*% (theta_0 - delta)))
)
poisson_data <- data.frame(y = y, x = x)

plot.ts(log(poisson_data$y))
plot.ts(poisson_data[, -1])

## ----data-setup-lasso---------------------------------------------------------
# Lasso
n <- 480
p_true <- 6
p <- 50
x <- mvtnorm::rmvnorm(n, rep(0, p), diag(p))
theta_0 <- rbind(
  runif(p_true, -5, -2),
  runif(p_true, -3, 3),
  runif(p_true, 2, 5),
  runif(p_true, -5, 5)
)
theta_0 <- cbind(theta_0, matrix(0, ncol = p - p_true, nrow = 4))
y <- c(
  x[1:80, ] %*% theta_0[1, ] + rnorm(80, 0, 1),
  x[81:200, ] %*% theta_0[2, ] + rnorm(120, 0, 1),
  x[201:320, ] %*% theta_0[3, ] + rnorm(120, 0, 1),
  x[321:n, ] %*% theta_0[4, ] + rnorm(160, 0, 1)
)
lasso_data <- data.frame(y = y, x = x)

plot.ts(lasso_data[, seq_len(p_true + 1)])

## ----data-setup-ar3-----------------------------------------------------------
# AR(3)
n <- 1000
x <- rep(0, n + 3)
for (i in 1:600) {
  x[i + 3] <- 0.6 * x[i + 2] - 0.2 * x[i + 1] + 0.1 * x[i] + rnorm(1, 0, 3)
}
for (i in 601:1000) {
  x[i + 3] <- 0.3 * x[i + 2] + 0.4 * x[i + 1] + 0.2 * x[i] + rnorm(1, 0, 3)
}
ar_data <- x[-seq_len(3)]

plot.ts(ar_data)

## ----data-setup-garch11-------------------------------------------------------
# GARCH(1, 1)
n <- 400
sigma_2 <- rep(1, n + 1)
x <- rep(0, n + 1)
for (i in seq_len(200)) {
  sigma_2[i + 1] <- 20 + 0.5 * x[i]^2 + 0.1 * sigma_2[i]
  x[i + 1] <- rnorm(1, 0, sqrt(sigma_2[i + 1]))
}
for (i in 201:400) {
  sigma_2[i + 1] <- 1 + 0.1 * x[i]^2 + 0.5 * sigma_2[i]
  x[i + 1] <- rnorm(1, 0, sqrt(sigma_2[i + 1]))
}
garch_data <- x[-1]

plot.ts(garch_data)

## ----univariate-mean-change-fastcpd-------------------------------------------
fastcpd::fastcpd.mean(mean_data_1, r.progress = FALSE)@cp_set

## ----univariate-mean-change-strucchange---------------------------------------
# Slow
strucchange::breakpoints(y ~ 1, data = data.frame(y = mean_data_1))$breakpoints

## ----univariate-mean-change-ecp-----------------------------------------------
# Slower
ecp::e.divisive(mean_data_1)$estimates

## ----univariate-mean-change-changepoint---------------------------------------
# Data need to be processed
changepoint::cpt.mean(c(mean_data_1))@cpts

## ----univariate-mean-change-breakfast-----------------------------------------
breakfast::breakfast(mean_data_1)$cptmodel.list[[6]]$cpts

## ----univariate-mean-change-wbs-----------------------------------------------
wbs::wbs(mean_data_1)$cpt$cpt.ic$mbic.penalty

## ----univariate-mean-change-mosum---------------------------------------------
# Data need to be processed. `G` is selected based on the example
if (interactive()) {
  mosum::mosum(c(mean_data_1), G = 40)$cpts.info$cpts
}

## ----univariate-mean-change-fpop----------------------------------------------
fpop::Fpop(mean_data_1, nrow(mean_data_1))$t.est

## ----univariate-mean-change-stepR---------------------------------------------
stepR::stepFit(mean_data_1, alpha = 0.5)$rightEnd

## ----univariate-mean-change-cpm-----------------------------------------------
cpm::processStream(mean_data_1, cpmType = "Student")$changePoints

## ----univariate-mean-change-segmented-----------------------------------------
segmented::segmented(
  lm(y ~ 1 + x, data.frame(y = mean_data_1, x = seq_len(nrow(mean_data_1)))),
  seg.Z = ~ x
)$psi[, "Est."]

## ----univariate-mean-change-mcp-----------------------------------------------
# Slowest
if (interactive()) {
  plot(
    mcp::mcp(
      list(y ~ 1, ~ 1, ~ 1),
      data = data.frame(y = mean_data_1, x = seq_len(nrow(mean_data_1))),
      par_x = "x"
    )
  )
}

## ----univariate-mean-change-not-----------------------------------------------
plot(not::not(mean_data_1, contrast = "pcwsConstMean"))

## ----univariate-mean-change-bcp-----------------------------------------------
# plot(bcp::bcp(mean_data_1))

## ----univariate-mean-and-or-variance-change-fastcpd---------------------------
fastcpd::fastcpd.mv(mv_data_1, r.progress = FALSE)@cp_set

## ----univariate-mean-and-or-variance-change-ecp-------------------------------
# Slow
ecp::e.divisive(mv_data_1)$estimates

## ----univariate-mean-and-or-variance-change-changepoint-----------------------
# Data need to be processed
changepoint::cpt.meanvar(c(mv_data_1))@cpts

## ----univariate-mean-and-or-variance-change-cpm-------------------------------
cpm::processStream(mv_data_1, cpmType = "GLR")$changePoints

## ----univariate-mean-and-or-variance-change-mcp-------------------------------
# Slower
if (interactive()) {
  plot(
    mcp::mcp(
      list(y ~ 1, ~ 1, ~ 1, ~ 1, ~ 1, ~ 1),
      data = data.frame(y = mv_data_1, x = seq_len(nrow(mv_data_1))),
      par_x = "x"
    )
  )
}

## ----univariate-mean-and-or-variance-change-not-------------------------------
plot(not::not(mv_data_1, contrast = "pcwsConstMeanVar"))

## ----multivariate-mean-change-fastcpd-----------------------------------------
fastcpd::fastcpd.mean(mean_data_3, r.progress = FALSE)@cp_set

## ----multivariate-mean-change-strucchange-------------------------------------
# Slow
strucchange::breakpoints(
  cbind(y.1, y.2, y.3) ~ 1, data = data.frame(y = mean_data_3)
)$breakpoints

## ----multivariate-mean-change-ecp---------------------------------------------
# Slower
ecp::e.divisive(mean_data_3)$estimates

## ----multivariate-mean-change-bcp---------------------------------------------
# plot(bcp::bcp(mean_data_3))

## ----multivariate-mean-and-or-variance-change-fastcpd-------------------------
fastcpd::fastcpd.mv(mv_data_3, r.progress = FALSE)@cp_set

## ----multivariate-mean-and-or-variance-change-ecp-----------------------------
# Slow
ecp::e.divisive(mv_data_3)$estimates

## ----linear-regression-fastcpd------------------------------------------------
fastcpd::fastcpd.lm(lm_data, r.progress = FALSE)@cp_set

## ----linear-regression-strucchange--------------------------------------------
strucchange::breakpoints(y ~ . - 1, data = lm_data)$breakpoints

## ----linear-regression-segmented----------------------------------------------
segmented::segmented(
  lm(
    y ~ . - 1,
    data.frame(y = lm_data$y, x = lm_data[, -1], index = seq_len(nrow(lm_data)))
  ),
  seg.Z = ~ index
)$psi[, "Est."]

## ----logistic-regression-fastcpd----------------------------------------------
fastcpd::fastcpd.binomial(binomial_data, r.progress = FALSE)@cp_set

## ----logistic-regression-strucchange------------------------------------------
strucchange::breakpoints(y ~ . - 1, data = binomial_data)$breakpoints

## ----poisson-regression-fastcpd-----------------------------------------------
fastcpd::fastcpd.poisson(poisson_data, r.progress = FALSE)@cp_set

## ----poisson-regression-strucchange-------------------------------------------
# Slow
strucchange::breakpoints(y ~ . - 1, data = poisson_data)$breakpoints

## ----lasso-fastcpd------------------------------------------------------------
fastcpd::fastcpd.lasso(lasso_data, r.progress = FALSE)@cp_set

## ----lasso-strucchange--------------------------------------------------------
# Slow
strucchange::breakpoints(y ~ . - 1, data = lasso_data)$breakpoints

## ----ar3-fastcpd--------------------------------------------------------------
fastcpd::fastcpd.ar(ar_data, 3, r.progress = FALSE)@cp_set

## ----ar3-segmented------------------------------------------------------------
segmented::segmented(
  lm(
    y ~ x + 1, data.frame(y = ar_data, x = seq_along(ar_data))
  ),
  seg.Z = ~ x
)$psi[, "Est."]

## ----ar3-mcp------------------------------------------------------------------
# Slow
if (interactive()) {
  plot(
    mcp::mcp(
      list(y ~ 1 + ar(3), ~ 0 + ar(3)),
      data = data.frame(y = ar_data, x = seq_along(ar_data)),
      par_x = "x"
    )
  )
}

## ----garch11-fastcpd----------------------------------------------------------
fastcpd::fastcpd.garch(garch_data, c(1, 1), r.progress = FALSE)@cp_set

## ----garch11-strucchange------------------------------------------------------
strucchange::breakpoints(x ~ 1, data = data.frame(x = garch_data))$breakpoints

