Runs a changepoint detection method on a sequence and returns a tidy
ggcpt result object. This is the recommended entry point for most
users. See cpt_methods() for the full method table with
engines and capabilities.
Usage
cpt_detect(
x,
method = "pelt",
change_in = "mean",
penalty = "MBIC",
index = NULL,
y = NULL,
...
)Arguments
- x
The series. A numeric vector for univariate methods, or a numeric matrix/data frame (rows are time points) for the multivariate methods — run
subset(cpt_methods(), multivariate)$methodfor the list. Ats,xts,zooor (unkeyed)tsibbleis accepted directly and its time index is carried through totidy()andautoplot(); so is a data frame together withy(and optionallyindex).- method
Detection method: any
methodincpt_methods()whosestatusis"available"or"registered". Methods whose engines live inSuggestsreport what to install when missing;cpt_register_method()adds detectors this package does not wrap.- change_in
What to detect change in. One of
"mean","var","meanvar","slope","distribution","covariance","network","regression"or"seasonality". Defaults to"mean". The requested value is validated against the method's capabilities (seecpt_methods()); incompatible combinations error rather than silently running something else.- penalty
Penalty type or value. Either a character string (
"MBIC","BIC","SIC","AIC","Hannan-Quinn","None") or a numeric penalty value. Defaults to"MBIC". See the penalty-semantics section ofcpt_penaltyfor how each engine interprets it; methods that use thresholds, significance levels, or posteriors instead of penalties ignore this argument, and"segneigh"falls back to"SIC"because changepoint does not implement MBIC for Segment Neighbourhood. Note also that the default"MBIC"is resolved to a numeric value for the numeric-penalty engines ("fpop","cpop","decafs"), and that value is stronger than those wrappers' own2 * log(n)default — 19.9 against 11.8 at \(n = 360\) — socpt_detect(x, method = "decafs")can report fewer changepoints thandecafs_wrapper(x)on the same series. Passpenaltyexplicitly to make the two entry points agree.- index
Optional time index, one value per observation (dates, say). Detection still runs on observation positions — every wrapped engine assumes an equally spaced sequence — but the index is stored on the result and threaded through
tidy()(ascp_index),augment(),autoplot()andcpt_report(), so the output speaks in the user's own units. An index that is not equally spaced warns. Whenxis a data frame andyis given,indexselects a column of that data frame instead of being a vector.- y
Column selection for the data-frame interface:
cpt_detect(df, y = value, index = date, method = "pelt"). A bare column name, a string, or a column position. Only meaningful whenxis a data frame; a data frame passed withoutykeeps its 0.4.0 meaning (one column per coordinate).- ...
Additional arguments passed to the specific wrapper (see the wrapper's help page for engine-specific options). Where an argument is also derived from
change_in(not'scontrast,cpm'scpm_type,kcp'srunning_stat,sn'sparameter,fastcpd'sfamily), a value supplied here takes precedence. Check the spelling against the wrapper's help page: several engines end their own signature in...(wbs, not, Rbeast, strucchange, segmented, fastcpd), so for those a misspelt argument name is silently discarded upstream and the engine quietly uses its default rather than reporting the typo.
Scale sensitivity of the penalised change-in-mean engines
"pelt", "binseg", "segneigh" and "fpop"
compare a penalty against a raw segment cost when
change_in = "mean": changepoint's Normal cost assumes a
noise standard deviation of 1, and fpop's lambda is an
absolute penalty on the residual sum of squares. Neither rescales the
data, so on a series whose noise is much wider than 1 the penalty is
effectively negligible and the segmentation shatters. On one true
changepoint with a jump of five standard deviations, "pelt"
returns 1 changepoint at \(\sigma = 1\), 29 at \(\sigma = 3\) and
138 at \(\sigma = 10\). Three ways to avoid it, in order of
convenience:
standardise the series first (
cpt_detect(scale(x)[, 1], method = "pelt"));pass a penalty on the data's own scale, for example
penalty = 2 * log(length(x)) * stats::var(diff(x)) / 2;use
change_in = "meanvar", which estimates a variance per segment and is unaffected.
The other engines are unaffected: SMUCE, WBS, WBS2, NOT, MOSUM, Isolate-Detect, TGUH, CPOP, DeCAFS and the Bayesian, nonparametric and multivariate methods all estimate or cancel the noise scale internally, and return the same segmentation whatever the units.
See also
cpt_methods() for what is available and what each
method can do. To get the result out: tidy.ggcpt(),
glance.ggcpt(), augment.ggcpt(),
summary.ggcpt() and print.ggcpt(). To
draw it: autoplot.ggcpt(). For the penalty:
cpt_penalty().
Examples
set.seed(2022)
x <- c(rnorm(100, 0, 1), rnorm(100, 10, 1))
result <- cpt_detect(x, method = "pelt", change_in = "mean")
result
#> ggcpt (changepoint detection result)
#> Method: pelt
#> Change in: mean
#> Changepoints found: 1
#> CP convention: left
#> Penalty: MBIC
#> Series length: 200
#>
#> Changepoints:
#> # A tibble: 1 × 2
#> cp cp_value
#> <int> <dbl>
#> 1 100 0.467
ggplot2::autoplot(result)
# A date index: detection is unchanged, but the report speaks in dates.
dates <- as.Date("2000-01-01") + 0:199
dated <- cpt_detect(x, method = "pelt", index = dates)
tidy(dated)
#> # A tibble: 1 × 3
#> cp cp_index cp_value
#> <int> <date> <dbl>
#> 1 100 2000-04-09 0.467
# The data-frame interface.
df <- data.frame(day = dates, value = x)
cpt_detect(df, y = value, index = day, method = "pelt")
#> ggcpt (changepoint detection result)
#> Method: pelt
#> Change in: mean
#> Changepoints found: 1
#> CP convention: left
#> Penalty: MBIC
#> Series length: 200
#> Index: 2000-01-01 to 2000-07-18
#>
#> Changepoints:
#> # A tibble: 1 × 3
#> cp cp_index cp_value
#> <int> <date> <dbl>
#> 1 100 2000-04-09 0.467
