Using BCPA on a one-dimensional variable

Elie Gurarie

November 14, 2018

Comments

The BCPA was originally formulated to analyze irregular movement data collected on marine mammals, but in essence it simply reduced movement data (X-Y-Time) to a univariate time-series. There are - in my opinion - better (i.e. more informative and more robust) tools for dealing with movement data specifically, (e.g. at https://github.com/EliGurarie/smoove), but the BCPA might still be useful for irregular univariate time series. An example (again from marine mammals) is depth data. A recent update to BCPA makes this analysis somewhat smoother. Here is an example on simulated data.

Note - to date this is available only on the GitHub version of BCPA, i.e. the first step is:

require(devtools)
install_github("EliGurarie/bcpa")

The code for this example can also be found in the help file for the WindowSweep() function.

Analysis

Depth data simulation

Load bcpa, and a few other handy packages:

require(magrittr)
require(lubridate)
require(bcpa)

We simulate some data with four phases / three change points: surface to medium to deep to surface, that occur at fixed times.

n.obs <- 100
time = (Sys.time() - dhours(runif(n.obs, 0, n.obs))) %>% sort

d1 <- 50; d2 <- 100
t1 <- 25; t2 <- 65; t3 <- 85
sd1 <- 1; sd2 <- 5; sd3 <- 10

dtime <- difftime(time, min(time), units="hours") %>% as.numeric
phases <- cut(dtime, c(-1, t1, t2, t3, 200), labels = c("P1","P2","P3","P4")) 
means <- c(0,d1,d2,0)[phases]
sds <- c(sd1,sd2,sd3,sd1)[phases]
depth <- rnorm(n.obs,means, sds)
# make all depths positive!
depth <- abs(depth)
mydata <- data.frame(time, depth)

The structure of the data is very simple:

head(mydata)
##                  time      depth
## 1 2022-05-23 08:36:42 0.32192527
## 2 2022-05-23 09:13:09 0.78383894
## 3 2022-05-23 09:40:42 1.57572752
## 4 2022-05-23 10:08:49 0.64289931
## 5 2022-05-23 10:24:15 0.08976065
## 6 2022-05-23 11:44:36 0.27655075

Plot simulated depth data

with(mydata, plot(time, depth, type = "o"))

Perform the window sweep. Note that you specify the response variable (depth) and the time variable (time):

depth.ws <- WindowSweep(mydata, variable = "depth", time.var = "time", windowsize = 25, windowstep = 1, progress=FALSE)

Here are some plots and the summary of the change point analysis:

plot(depth.ws, ylab = "Depth (m)")

plot(depth.ws, type = "flat", cluster = 8, ylab = "Depth (m)")

ChangePointSummary(depth.ws, cluster = 8)
## $breaks
##   X1   middle size modelmode        middle.POSIX
## 1  1 25.46224   27         4 2022-05-24 09:58:01
## 2  2 62.47157   18         4 2022-05-25 22:46:30
## 3  3 84.46078   12         4 2022-05-26 20:34:54
## 
## $phases
##         t.cut    mu.hat     s.hat      rho.hat       t0       t1 interval
## 1   (-1,25.5]  3.681865 11.256694 1.4733085237 -1.00000 25.46224 26.46224
## 2 (25.5,62.5] 50.063357  4.367361 0.0005596285 25.46224 62.47157 37.00933
## 3 (62.5,84.5] 91.941686 17.048889 0.0883214493 62.47157 84.46078 21.98921
## 4 (84.5,98.9]  6.434163 22.852427 0.0613947945 84.46078 98.86528 14.40450

This is a pretty artificial example, but it works well.