Detects 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_pvalue(
  data,
  q_max = 4,
  n = 10000,
  min_move_dist = 0,
  clu = NULL,
  seed = NULL,
  ...
)

# S3 method for class 'trackframe'
change_point_test_pvalue(
  data,
  q_max = 4,
  n = 10000,
  min_move_dist = 0,
  clu = NULL,
  seed = NULL,
  ...
)

# S3 method for class 'data.frame'
change_point_test_pvalue(
  data,
  q_max = 4,
  n = 10000,
  min_move_dist = 0,
  clu = NULL,
  seed = NULL,
  tf_args = list(crs = NA),
  ...
)

# S3 method for class 'move2'
change_point_test_pvalue(
  data,
  q_max = q_max,
  n = n,
  min_move_dist = 0,
  clu = NULL,
  seed = NULL,
  ...
)

# S3 method for class 'sftrack'
change_point_test_pvalue(
  data,
  q_max = q_max,
  n = n,
  min_move_dist = 0,
  clu = NULL,
  seed = NULL,
  ...
)

Arguments

data

a matrix or data frame with columns for x-coordinates, y-coordinates, time, and track id. For the default method, this should be a matrix or data frame with at least 3 columns.

q_max

an integer specifying the maximum value of q.

n

an integer specifying the number of random permutations for the permutation test Higher values provide more accurate p-values but increase computation time.

min_move_dist

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)

clu

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

seed to be passed to random number generator

...

additional arguments passed to methods.

tf_args

args passed to as.trackframe in the case "data" is not

Value

a list with one element per track id and a matrix an additional column indicating

cp_id

Sequential numbering of detected change points

Details

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.

Examples

library(cpt)
data("cpttestdata", package = "cpt")

pvalues <- change_point_test_pvalue(cpttestdata, q_max = 6, n = 100)
pvalues
#> $track_1
#>         q=1  q=2  q=3  q=4  q=5  q=6
#>   [1,] 1.00 0.72 0.29 0.44 0.34 0.29
#>   [2,]   NA   NA   NA   NA   NA   NA
#>   [3,]   NA   NA   NA   NA   NA   NA
#>   [4,]   NA   NA   NA   NA   NA   NA
#>   [5,]   NA   NA   NA   NA   NA   NA
#>   [6,]   NA   NA   NA   NA   NA   NA
#>   [7,]   NA   NA   NA   NA   NA   NA
#>   [8,] 0.33 0.40 0.33 0.30 0.17 0.16
#>   [9,] 1.00 0.88 0.92 0.91 1.00 1.00
#>  [10,] 0.39 0.34 0.45 0.42 0.12 0.12
#>  [11,] 1.00 0.89 0.63 0.45 0.31 0.20
#>  [12,]   NA   NA   NA   NA   NA   NA
#>  [13,]   NA   NA   NA   NA   NA   NA
#>  [14,]   NA   NA   NA   NA   NA   NA
#>  [15,]   NA   NA   NA   NA   NA   NA
#>  [16,]   NA   NA   NA   NA   NA   NA
#>  [17,] 0.83 0.49 0.26 0.27 0.12 0.04
#>  [18,] 0.28 0.13 0.13 0.07 0.03 0.03
#>  [19,] 0.51 0.34 0.15 0.17 0.15 0.11
#>  [20,] 0.50 0.39 0.25 0.20 0.39 0.38
#>  [21,] 0.58 0.39 0.42 0.59 0.48 0.51
#>  [22,]   NA   NA   NA   NA   NA   NA
#>  [23,] 0.76 0.47 0.80 0.67 0.75 0.78
#>  [24,] 0.49 0.75 0.77 0.88 0.89 0.79
#>  [25,] 0.46 0.92 0.80 0.87 0.60 0.69
#>  [26,] 0.46 0.67 0.76 0.87 0.92 0.90
#>  [27,] 1.00 0.93 0.57 0.77 0.69 0.73
#>  [28,]   NA   NA   NA   NA   NA   NA
#>  [29,]   NA   NA   NA   NA   NA   NA
#>  [30,]   NA   NA   NA   NA   NA   NA
#>  [31,]   NA   NA   NA   NA   NA   NA
#>  [32,]   NA   NA   NA   NA   NA   NA
#>  [33,]   NA   NA   NA   NA   NA   NA
#>  [34,]   NA   NA   NA   NA   NA   NA
#>  [35,]   NA   NA   NA   NA   NA   NA
#>  [36,]   NA   NA   NA   NA   NA   NA
#>  [37,]   NA   NA   NA   NA   NA   NA
#>  [38,]   NA   NA   NA   NA   NA   NA
#>  [39,]   NA   NA   NA   NA   NA   NA
#>  [40,]   NA   NA   NA   NA   NA   NA
#>  [41,]   NA   NA   NA   NA   NA   NA
#>  [42,]   NA   NA   NA   NA   NA   NA
#>  [43,]   NA   NA   NA   NA   NA   NA
#>  [44,]   NA   NA   NA   NA   NA   NA
#>  [45,]   NA   NA   NA   NA   NA   NA
#>  [46,]   NA   NA   NA   NA   NA   NA
#>  [47,]   NA   NA   NA   NA   NA   NA
#>  [48,]   NA   NA   NA   NA   NA   NA
#>  [49,]   NA   NA   NA   NA   NA   NA
#>  [50,]   NA   NA   NA   NA   NA   NA
#>  [51,]   NA   NA   NA   NA   NA   NA
#>  [52,]   NA   NA   NA   NA   NA   NA
#>  [53,]   NA   NA   NA   NA   NA   NA
#>  [54,]   NA   NA   NA   NA   NA   NA
#>  [55,]   NA   NA   NA   NA   NA   NA
#>  [56,]   NA   NA   NA   NA   NA   NA
#>  [57,]   NA   NA   NA   NA   NA   NA
#>  [58,]   NA   NA   NA   NA   NA   NA
#>  [59,]   NA   NA   NA   NA   NA   NA
#>  [60,]   NA   NA   NA   NA   NA   NA
#>  [61,] 1.00 0.68 0.81 0.71 0.64 0.57
#>  [62,] 0.43 0.66 0.59 0.60 0.54 0.36
#>  [63,] 0.50 0.56 0.93 0.84 0.74 0.85
#>  [64,] 0.89 0.85 0.65 0.50 0.64 0.42
#>  [65,] 0.89 0.77 0.64 0.59 0.39 0.36
#>  [66,] 0.83 0.58 0.81 0.42 0.39 0.84
#>  [67,] 0.42 0.63 0.36 0.58 0.98 0.84
#>  [68,] 0.30 0.71 0.84 0.83 0.68 0.57
#>  [69,] 0.50 0.66 0.95 0.85 0.74 0.44
#>  [70,]   NA   NA   NA   NA   NA   NA
#>  [71,]   NA   NA   NA   NA   NA   NA
#>  [72,]   NA   NA   NA   NA   NA   NA
#>  [73,]   NA   NA   NA   NA   NA   NA
#>  [74,]   NA   NA   NA   NA   NA   NA
#>  [75,] 0.92 0.36 0.37 0.30 0.17 0.21
#>  [76,] 0.49 0.28 0.22 0.12 0.08 0.10
#>  [77,] 0.80 0.40 0.08 0.25 0.12 0.17
#>  [78,] 0.36 0.18 0.16 0.18 0.22 0.23
#>  [79,] 0.57 0.33 0.16 0.31 0.38 0.27
#>  [80,] 0.58 0.29 0.53 0.80 0.48 0.72
#>  [81,] 0.43 0.66 0.88 0.68 0.89 0.54
#>  [82,] 1.00 0.94 0.93 0.97 0.32 0.15
#>  [83,]   NA   NA   NA   NA   NA   NA
#>  [84,] 0.89 0.91 0.93 0.25 0.10 0.04
#>  [85,] 0.42 0.34 0.03 0.04 0.01 0.05
#>  [86,] 0.13 0.02 0.01 0.02 0.03 0.02
#>  [87,]   NA   NA   NA   NA   NA   NA
#>  [88,]   NA   NA   NA   NA   NA   NA
#>  [89,]   NA   NA   NA   NA   NA   NA
#>  [90,]   NA   NA   NA   NA   NA   NA
#>  [91,]   NA   NA   NA   NA   NA   NA
#>  [92,]   NA   NA   NA   NA   NA   NA
#>  [93,]   NA   NA   NA   NA   NA   NA
#>  [94,]   NA   NA   NA   NA   NA   NA
#>  [95,]   NA   NA   NA   NA   NA   NA
#>  [96,] 0.08 0.02 0.01 0.02 0.04 0.01
#>  [97,] 0.36 0.18 0.23 0.24 0.06 0.04
#>  [98,] 0.72 0.50 0.41 0.15 0.04 0.03
#>  [99,] 0.54 0.63 0.12 0.07 0.03 0.04
#> [100,] 1.00 0.17 0.04 0.03 0.05 0.02
#> [101,] 0.10 0.01 0.01 0.02 0.01 0.01
#> [102,] 0.08 0.06 0.14 0.10 0.02 0.01
#> [103,] 0.47 0.62 0.38 0.02 0.01 0.01
#> [104,] 0.34 0.17 0.01 0.01 0.01 0.01
#> [105,] 0.39 0.02 0.01 0.01 0.01 0.01
#> [106,]   NA   NA   NA   NA   NA   NA
#> [107,]   NA   NA   NA   NA   NA   NA
#> [108,]   NA   NA   NA   NA   NA   NA
#> [109,]   NA   NA   NA   NA   NA   NA
#> [110,]   NA   NA   NA   NA   NA   NA
#> [111,] 0.04 0.02 0.01 0.01 0.01 0.01
#> [112,] 0.04 0.01 0.02 0.01 0.01 0.01
#> [113,] 0.03 0.07 0.01 0.02 0.02 0.02
#> [114,] 0.57 0.05 0.02 0.04 0.03 0.03
#> [115,] 0.03 0.04 0.03 0.06 0.04 0.07
#> [116,] 0.19 0.38 0.30 0.35 0.40 0.43
#> [117,] 0.48 0.37 0.65 0.37 0.56 0.56
#> [118,] 0.53 0.58 0.63 0.82 0.54 0.52
#> [119,]   NA   NA   NA   NA   NA   NA
#> [120,] 0.84 0.79 0.74 0.81 0.83 0.98
#> [121,] 0.45 0.46 0.70 0.42 0.79 0.55
#> [122,] 0.82 0.73 0.74 0.90 0.82   NA
#> [123,]   NA   NA   NA   NA   NA   NA
#> [124,]   NA   NA   NA   NA   NA   NA
#> [125,]   NA   NA   NA   NA   NA   NA
#> [126,]   NA   NA   NA   NA   NA   NA
#> [127,]   NA   NA   NA   NA   NA   NA
#> [128,]   NA   NA   NA   NA   NA   NA
#> [129,]   NA   NA   NA   NA   NA   NA
#> [130,]   NA   NA   NA   NA   NA   NA
#> [131,]   NA   NA   NA   NA   NA   NA
#> [132,]   NA   NA   NA   NA   NA   NA
#> [133,]   NA   NA   NA   NA   NA   NA
#> [134,]   NA   NA   NA   NA   NA   NA
#> [135,]   NA   NA   NA   NA   NA   NA
#> [136,]   NA   NA   NA   NA   NA   NA
#> [137,]   NA   NA   NA   NA   NA   NA
#> [138,]   NA   NA   NA   NA   NA   NA
#> [139,] 0.58 0.55 0.66 0.93   NA   NA
#> [140,] 0.43 0.82 0.47   NA   NA   NA
#> [141,] 0.96 0.84   NA   NA   NA   NA
#> [142,]   NA   NA   NA   NA   NA   NA
#> [143,]   NA   NA   NA   NA   NA   NA
#> [144,]   NA   NA   NA   NA   NA   NA
#> [145,]   NA   NA   NA   NA   NA   NA
#> [146,]   NA   NA   NA   NA   NA   NA
#> [147,]   NA   NA   NA   NA   NA   NA
#> [148,] 0.48   NA   NA   NA   NA   NA
#> [149,]   NA   NA   NA   NA   NA   NA
#> [150,]   NA   NA   NA   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_pvalue(cpttestdata, q_max = 3, n = 100, min_move_dist = 0)

df <- cpttestdata
class(df)
#> [1] "data.frame"
set.seed(2025L)
cpt_df <- change_point_test_pvalue(df, q_max = 3, n = 100, min_move_dist = 0)

library(move2)
data("path_move2", package = "trackframe")
class(path_move2)
#> [1] "move2"      "sf"         "data.frame"
set.seed(2025L)
cpt_move2 <- change_point_test_pvalue(path_move2[1:200,], q_max = 3, n = 100, min_move_dist = 0)

library(sftrack)
data("path_sftrack", package = "trackframe")
class(path_sftrack)
#> [1] "sftrack"    "sf"         "data.frame"
set.seed(2025L)
cpt_sftrack <- change_point_test_pvalue(path_sftrack[1:200,], q_max = 3, n = 100,
  min_move_dist = 0)