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",
  relevance = NULL
)

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.

relevance

Optional smallest change worth acting on, in noise standard deviations. The null hypothesis becomes "the change is no larger than relevance" rather than "there is no change", so a statistically detectable but practically negligible shift is not significant. Applies to the Welch route (the changepoints of a series fit); the p_value column is then the relevance test's, and a relevance column records the threshold in the data's units.

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. The exception is a changepoint that was fixed in advance, through cpt_detect(fixed = ): its row is TRUE.

  • The fallback compares means whatever the fit detected, so on a fit of a change in variance, slope or distribution it tests a different change from the one found, and warns (class ggchangepoint_assumption).

  • 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