Skip to contents

Attaches a test to each detected changepoint (type = "jump") or to each fitted segment (type = "segment"), using the engine's own test where it has one and an explicitly unadjusted two-sample test where it does not.

Usage

cpt_test(object, type = c("jump", "segment"), correction = "none")

Arguments

object

A ggcpt object.

type

"jump" (one row per changepoint: is the change at this location real?) or "segment" (one row per segment: does this segment differ from the one before it?).

correction

Multiple-testing correction applied across the rows, one of the p.adjust methods ("none", "bonferroni", "holm", "BH", ...). Defaults to "none"; a p_adjusted column is added when it is not.

Value

A tibble with columns cp (or seg_id), estimate, statistic, p_value, method and selection_adjusted, plus cp_index on the original scale when the result carries a time index (as cpt_confint() does), and p_adjusted when correction is not "none". estimate is the change in the segment mean (the breakpoint's slope change for segmented), and NA for a regression-mode strucchange fit, whose change is a vector of coefficients; its Chow test is run on the full regression model. A multivariate result is refused: both routes test one series.

Selection bias

read this before quoting a p-value: Testing a changepoint at a location that was chosen because the data looked like it changed there is circular, and the resulting p-values are anti-conservative, often severely. The selection_adjusted column records, per row, whether the test accounts for that:

  • TRUE for segmented's Davies test, which is built for a nuisance parameter present only under the alternative. It is one global test of "is there a breakpoint", not a test per breakpoint, so on a multi-break fit every row carries the same statistic and p-value, and the method string says so.

  • FALSE for the generic Welch two-sample fallback, which compares the segments either side of the changepoint as if the location had been fixed in advance. Useful as a descriptive effect size with a scale attached; not a valid significance test for the existence of the change.

  • FALSE for strucchange's route as well, which is the Chow F evaluated at each estimated break date. The Chow statistic's reference distribution assumes the date was fixed in advance, so quoting it at a date the Bai-Perron dynamic program chose is exactly the circularity this column exists to flag. Reporting it is conventional in that literature, which does not make it adjusted. The selection-adjusted objects there are the sup-type statistics and the Bai-Perron critical values.

Two further limits worth knowing. type = "segment" is always the unadjusted Welch test: the native routes above apply only to type = "jump", so a segmented fit tested per-segment does not use Davies' test. And the split above is by engine and type, not by engine alone. For a guarantee that survives selection, use nsp_wrapper() (regions with exact global coverage) or cpt_confint() with method = "nsp". The canonical post-detection tests of Jewell, Fearnhead and Witten (2022) are implemented in ChangepointInference, which is not on CRAN; cpt_register_method() is the supported way to bring it in.

Examples

set.seed(2026)
fit <- cpt_detect(c(rnorm(60), rnorm(60, 4)), method = "pelt")
cpt_test(fit)
#> Warning: `selection_adjusted` is FALSE for 1 of 1 row(s): the changepoint locations were chosen from these data, so those p-values are anti-conservative. See the selection-bias section of ?cpt_test.
#> # A tibble: 1 × 6
#>      cp estimate statistic  p_value method                    selection_adjusted
#>   <int>    <dbl>     <dbl>    <dbl> <chr>                     <lgl>             
#> 1    60     4.01      21.5 3.24e-42 Welch two-sample t (unad… FALSE