change_point_test.RdDetects significant change points in animal movement trajectory data using a permutation-based approach. This function identifies locations where the movement pattern significantly changes, which can represent behavioral transitions or responses to environmental stimuli.
change_point_test(
data,
alpha = 0.05,
q = 4,
n = 10000,
min_move_dist = 0,
clu = NULL,
seed = NULL,
...
)
# S3 method for class 'trackframe'
change_point_test(
data,
alpha = 0.05,
q = 4,
n = 1000,
min_move_dist = 0,
clu = NULL,
seed = NULL,
...
)
# S3 method for class 'data.frame'
change_point_test(
data,
alpha = 0.05,
q = 4,
n = 1000,
min_move_dist = 0,
clu = NULL,
seed = NULL,
tf_args = list(crs = NA),
...
)
# S3 method for class 'move2'
change_point_test(
data,
alpha = 0.05,
q = 4,
n = 1000,
min_move_dist = 0,
clu = NULL,
seed = NULL,
...
)
# S3 method for class 'sftrack'
change_point_test(
data,
alpha = 0.05,
q = 4,
n = 1000,
min_move_dist = 0,
clu = NULL,
seed = NULL,
...
)a trackframe, or an object coercible to trackframe
a numeric value specifying the significance level for detecting change points.
an integer specifying the minimum segment length between potential change points.
an integer specifying the number of random permutations for thepermutation test. Higher values provide more accurate p-values but increase computation time.
a numeric value specifying the minimum distance between two positions to be distinguishable. Points with movements smaller than this threshold will be considered stationary.(tol parameter in original code)
optional parameter determining whether parallelization with the parallel package is
used.
Either of class "NULL", "numeric", or "cluster":
If NULL (default) no parallel processing is used.
If of class "numeric", it gives the number of cores,
passed as integer to parallel::makePSOCKcluster.
If of class "cluster", it is assumed to be a cluster object from parallel
package. Allowed is any object which inherits from "cluster" and can be passed to
parallel::parLapply.
seed to be passed to random number generator
additional arguments passed to methods.
args passed to as.trackframe in the case "data" is not
already a trackframe
An augmented data frame containing the original data with additional columns:
Sequential numbering of detected change points
This function implements a sequential change point detection algorithm that uses a permutation test to identify significant changes in movement patterns. It compares the sum of distances between consecutive points against randomly permuted sequences to determine if a change point exists.
The first point in the trajectory is never considered a change point, as it represents the starting location.
library("cpt")
# First detect change points
set.seed(2025L)
cpt <- change_point_test(cpttestdata, alpha = 0.05, q = 3, n = 500)
# Second show the change points in a summarized format
summary(cpt)
#> first last east north id
#> track_1.1 2025-01-01 00:38:00 2025-01-01 00:38:00 588443.2 703275.0 track_1
#> track_1.2 2025-01-01 00:54:00 2025-01-01 00:54:00 587898.1 703728.7 track_1
# with trackframe
library("trackframe")
#>
#> Attaching package: ‘trackframe’
#> The following object is masked from ‘package:zoo’:
#>
#> time<-
df <- data.frame(x = cpttestdata[, 1],
y = cpttestdata[, 2],
t = as.POSIXct(seq_along(cpttestdata[, 3])),
id = "track_1")
tf <- as.trackframe(df, time_col = 't', easting_col = 'x', northing_col = 'y', crs = NA)
set.seed(2025L)
cpt_tf <- change_point_test(tf, alpha = 0.05, q = 3, n = 500, min_move_dist = 0)
summary(cpt_tf)
#> first last east north id
#> track_1.1 1970-01-01 00:00:39 1970-01-01 00:00:39 588443.2 703275.0 track_1
#> track_1.2 1970-01-01 00:00:55 1970-01-01 00:00:55 587898.1 703728.7 track_1
# Get probability values instead of binary indicators
pvalues <- change_point_test_pvalue(
cpttestdata[, c("x", "y", "t", "track_id")], q_max = 3, n = 500)
pvalues
#> $track_1
#> q=1 q=2 q=3
#> [1,] 1.000 0.676 0.246
#> [2,] NA NA NA
#> [3,] NA NA NA
#> [4,] NA NA NA
#> [5,] NA NA NA
#> [6,] NA NA NA
#> [7,] NA NA NA
#> [8,] 0.356 0.330 0.372
#> [9,] 1.000 0.876 0.900
#> [10,] 0.410 0.402 0.562
#> [11,] 1.000 0.840 0.624
#> [12,] NA NA NA
#> [13,] NA NA NA
#> [14,] NA NA NA
#> [15,] NA NA NA
#> [16,] NA NA NA
#> [17,] 0.846 0.482 0.282
#> [18,] 0.244 0.148 0.140
#> [19,] 0.532 0.348 0.244
#> [20,] 0.474 0.342 0.284
#> [21,] 0.528 0.356 0.346
#> [22,] NA NA NA
#> [23,] 0.768 0.520 0.796
#> [24,] 0.480 0.838 0.758
#> [25,] 0.530 0.874 0.836
#> [26,] 0.438 0.636 0.786
#> [27,] 1.000 0.992 0.576
#> [28,] NA NA NA
#> [29,] NA NA NA
#> [30,] NA NA NA
#> [31,] NA NA NA
#> [32,] NA NA NA
#> [33,] NA NA NA
#> [34,] NA NA NA
#> [35,] NA NA NA
#> [36,] NA NA NA
#> [37,] NA NA NA
#> [38,] NA NA NA
#> [39,] NA NA NA
#> [40,] NA NA NA
#> [41,] NA NA NA
#> [42,] NA NA NA
#> [43,] NA NA NA
#> [44,] NA NA NA
#> [45,] NA NA NA
#> [46,] NA NA NA
#> [47,] NA NA NA
#> [48,] NA NA NA
#> [49,] NA NA NA
#> [50,] NA NA NA
#> [51,] NA NA NA
#> [52,] NA NA NA
#> [53,] NA NA NA
#> [54,] NA NA NA
#> [55,] NA NA NA
#> [56,] NA NA NA
#> [57,] NA NA NA
#> [58,] NA NA NA
#> [59,] NA NA NA
#> [60,] NA NA NA
#> [61,] 1.000 0.624 0.750
#> [62,] 0.418 0.676 0.534
#> [63,] 0.454 0.542 0.910
#> [64,] 0.868 0.834 0.660
#> [65,] 0.898 0.696 0.532
#> [66,] 0.750 0.572 0.690
#> [67,] 0.486 0.662 0.400
#> [68,] 0.346 0.636 0.772
#> [69,] 0.548 0.598 0.944
#> [70,] NA NA NA
#> [71,] NA NA NA
#> [72,] NA NA NA
#> [73,] NA NA NA
#> [74,] NA NA NA
#> [75,] 0.904 0.316 0.382
#> [76,] 0.466 0.298 0.244
#> [77,] 0.770 0.386 0.230
#> [78,] 0.372 0.208 0.156
#> [79,] 0.450 0.298 0.134
#> [80,] 0.694 0.324 0.544
#> [81,] 0.392 0.690 0.854
#> [82,] 1.000 0.940 0.894
#> [83,] NA NA NA
#> [84,] 0.878 0.914 0.900
#> [85,] 0.436 0.328 0.022
#> [86,] 0.154 0.008 0.008
#> [87,] NA NA NA
#> [88,] NA NA NA
#> [89,] NA NA NA
#> [90,] NA NA NA
#> [91,] NA NA NA
#> [92,] NA NA NA
#> [93,] NA NA NA
#> [94,] NA NA NA
#> [95,] NA NA NA
#> [96,] 0.064 0.012 0.006
#> [97,] 0.412 0.232 0.210
#> [98,] 0.670 0.362 0.446
#> [99,] 0.620 0.660 0.158
#> [100,] 1.000 0.206 0.020
#> [101,] 0.072 0.008 0.004
#> [102,] 0.108 0.024 0.116
#> [103,] 0.494 0.532 0.330
#> [104,] 0.420 0.204 0.002
#> [105,] 0.460 0.006 0.002
#> [106,] NA NA NA
#> [107,] NA NA NA
#> [108,] NA NA NA
#> [109,] NA NA NA
#> [110,] NA NA NA
#> [111,] 0.020 0.004 0.002
#> [112,] 0.048 0.002 0.006
#> [113,] 0.050 0.058 0.008
#> [114,] 0.564 0.022 0.016
#> [115,] 0.052 0.024 0.022
#> [116,] 0.172 0.350 0.256
#> [117,] 0.478 0.362 0.592
#> [118,] 0.506 0.656 0.630
#> [119,] NA NA NA
#> [120,] 0.834 0.866 0.836
#> [121,] 0.464 0.440 0.700
#> [122,] 0.838 0.740 0.734
#> [123,] NA NA NA
#> [124,] NA NA NA
#> [125,] NA NA NA
#> [126,] NA NA NA
#> [127,] NA NA NA
#> [128,] NA NA NA
#> [129,] NA NA NA
#> [130,] NA NA NA
#> [131,] NA NA NA
#> [132,] NA NA NA
#> [133,] NA NA NA
#> [134,] NA NA NA
#> [135,] NA NA NA
#> [136,] NA NA NA
#> [137,] NA NA NA
#> [138,] NA NA NA
#> [139,] 0.602 0.548 0.792
#> [140,] 0.454 0.792 0.502
#> [141,] 0.888 0.858 NA
#> [142,] NA NA NA
#> [143,] NA NA NA
#> [144,] NA NA NA
#> [145,] NA NA NA
#> [146,] NA NA NA
#> [147,] NA NA NA
#> [148,] 0.442 NA NA
#> [149,] NA NA NA
#> [150,] NA NA NA
#> attr(,"class")
#> [1] "change_point_test_pvalue" "matrix"
#> [3] "array"
#>
#> attr(,"class")
#> [1] "change_point_test_pvalue_collection" "list"
set.seed(2025L)
cpt_tf <- change_point_test(cpttestdata, alpha = 0.05, q = 3, n = 500, min_move_dist = 0)
summary(cpt_tf)
#> first last east north id
#> track_1.1 2025-01-01 00:38:00 2025-01-01 00:38:00 588443.2 703275.0 track_1
#> track_1.2 2025-01-01 00:54:00 2025-01-01 00:54:00 587898.1 703728.7 track_1
df <- cpttestdata
class(df)
#> [1] "data.frame"
set.seed(2025L)
cpt_df <- change_point_test(df, alpha = 0.05, q = 3, n = 500, min_move_dist = 0)
summary(cpt_df)
#> first last east north id
#> track_1.1 2025-01-01 00:38:00 2025-01-01 00:38:00 588443.2 703275.0 track_1
#> track_1.2 2025-01-01 00:54:00 2025-01-01 00:54:00 587898.1 703728.7 track_1
library(move2)
data("path_move2", package = "trackframe")
class(path_move2)
#> [1] "move2" "sf" "data.frame"
set.seed(2025L)
cpt_move2 <- change_point_test(path_move2, alpha = 0.05, q = 3, n = 500, min_move_dist = 0)
summary(cpt_move2)
#> first last east north
#> 1 2025-10-15 00:22:34 2025-10-15 00:22:34 -0.0072061100 0.003763871
#> 2 2025-10-15 13:43:34 2025-10-15 13:43:34 -0.0027773379 0.011703586
#> 3 2025-10-15 18:00:34 2025-10-15 18:07:34 0.0002694329 0.009003683
#> 4 2025-10-15 18:49:34 2025-10-15 18:49:34 0.0013820211 0.017076390
#> 5 2025-10-15 20:58:34 2025-10-15 20:58:34 -0.0049726251 0.016002070
#> 6 2025-10-15 23:43:34 2025-10-15 23:43:34 0.0005152087 0.015387244
#> 7 2025-10-16 02:39:34 2025-10-16 02:39:34 -0.0059711263 0.017819524
#> 8 2025-10-16 04:09:34 2025-10-16 04:09:34 -0.0038805680 0.014830813
#> 9 2025-10-16 07:16:34 2025-10-16 07:16:34 -0.0048342032 0.021118660
#> 10 2025-10-16 15:45:34 2025-10-16 15:45:34 -0.0007020970 0.011519583
#> 11 2025-10-16 16:17:34 2025-10-16 16:17:34 -0.0040944078 0.011046036
#> 12 2025-10-16 18:39:34 2025-10-16 18:39:34 0.0005950734 0.007295949
#> 13 2025-10-16 21:48:34 2025-10-16 21:48:34 -0.0050339505 0.004651530
#> 14 2025-10-16 22:02:34 2025-10-16 22:29:34 -0.0031042727 0.008906007
#> 15 2025-10-17 04:37:34 2025-10-17 04:37:34 -0.0053506489 0.005985680
library(sftrack)
data("path_sftrack", package = "trackframe")
class(path_sftrack)
#> [1] "sftrack" "sf" "data.frame"
set.seed(2025L)
cpt_sftrack <- change_point_test(path_sftrack, alpha = 0.05, q = 3, n = 500, min_move_dist = 0)
summary(cpt_sftrack)
#> first last east north
#> 1 2025-10-15 00:22:34 2025-10-15 00:22:34 -0.0072061100 0.003763871
#> 2 2025-10-15 13:43:34 2025-10-15 13:43:34 -0.0027773379 0.011703586
#> 3 2025-10-15 18:00:34 2025-10-15 18:07:34 0.0002694329 0.009003683
#> 4 2025-10-15 18:49:34 2025-10-15 18:49:34 0.0013820211 0.017076390
#> 5 2025-10-15 20:58:34 2025-10-15 20:58:34 -0.0049726251 0.016002070
#> 6 2025-10-15 23:43:34 2025-10-15 23:43:34 0.0005152087 0.015387244
#> 7 2025-10-16 02:39:34 2025-10-16 02:39:34 -0.0059711263 0.017819524
#> 8 2025-10-16 04:09:34 2025-10-16 04:09:34 -0.0038805680 0.014830813
#> 9 2025-10-16 07:16:34 2025-10-16 07:16:34 -0.0048342032 0.021118660
#> 10 2025-10-16 15:45:34 2025-10-16 15:45:34 -0.0007020970 0.011519583
#> 11 2025-10-16 16:17:34 2025-10-16 16:17:34 -0.0040944078 0.011046036
#> 12 2025-10-16 18:39:34 2025-10-16 18:39:34 0.0005950734 0.007295949
#> 13 2025-10-16 21:48:34 2025-10-16 21:48:34 -0.0050339505 0.004651530
#> 14 2025-10-16 22:02:34 2025-10-16 22:29:34 -0.0031042727 0.008906007
#> 15 2025-10-17 04:37:34 2025-10-17 04:37:34 -0.0053506489 0.005985680