change_point
change_point ¤
Change-point detection: where did the process level (or spread) shift?
Offline segmentation of one signal into stretches with constant mean (and optionally constant variance) using PELT, the exact pruned dynamic program of Killick, Fearnhead & Eckley (2012). Unlike a CUSUM or a rolling-window test it finds all change points at once, places them at the exact sample, and needs no window length. Typical uses: a tool change, a new raw-material lot, a recalibration, a drifting setpoint that was corrected.
The implementation is plain numpy (no extra dependency). Costs are Gaussian negative log-likelihoods computed from cumulative sums, so each candidate segment costs O(1).
ChangePointEvents ¤
ChangePointEvents(
dataframe: DataFrame,
signal_uuid: str,
*,
value_column: str = "value_double",
event_uuid: str = "quality:change_point",
time_column: str = "systime"
)
Bases: Base
Quality: change-point detection (PELT).
- detect_change_points: One point event per detected shift, with the level and spread before and after.
- segment_statistics: The stable stretches between change points as intervals with their mean, std and sample count.
Example
import ts_shape df = ts_shape.make_timeseries(["pressure"], n_points=100) df.loc[50:, "value_double"] += 5 # level shift half-way out = ts_shape.ChangePointEvents(df, "pressure").detect_change_points() numbers = ["mean_before", "mean_after", "shift_sigma"] out[["systime", *numbers]].round(dict.fromkeys(numbers, 1)) systime mean_before mean_after shift_sigma 0 2025-01-01 00:25:00 100.1 104.8 6.1
detect_change_points ¤
detect_change_points(
cost: Cost = "normal_mean",
penalty: float | None = None,
min_size: int = 5,
method: Method = "auto",
) -> pd.DataFrame
Detect level (and optionally spread) shifts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost
|
Cost
|
|
'normal_mean'
|
penalty
|
float | None
|
Cost of one change point; |
None
|
min_size
|
int
|
Minimum samples per segment. |
5
|
method
|
Method
|
|
'auto'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Point events at the first sample of each new segment: |
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
(the shift in units of the pooled segment std). |
segment_statistics ¤
segment_statistics(
cost: Cost = "normal_mean",
penalty: float | None = None,
min_size: int = 5,
method: Method = "auto",
) -> pd.DataFrame
The stable segments between change points.
A segment holds until the first sample of the next one; the last segment ends at the last sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost
|
Cost
|
As in :meth: |
'normal_mean'
|
penalty
|
float | None
|
As in :meth: |
None
|
min_size
|
int
|
As in :meth: |
5
|
method
|
Method
|
As in :meth: |
'auto'
|
Returns:
| Name | Type | Description |
|---|---|---|
Intervals |
DataFrame
|
|
DataFrame
|
|
pelt ¤
pelt(
x: ndarray,
*,
cost: Cost = "normal_mean",
penalty: float | None = None,
min_size: int = 2
) -> list[int]
Optimal change points of x under a penalized Gaussian cost (PELT).
Exact: returns the segmentation minimizing total cost plus penalty
per change. Runtime is near-linear when changes are frequent and
quadratic when they are rare; for long series with few changes use
:func:binseg or resample first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
ndarray
|
1-D finite values. |
required |
cost
|
Cost
|
|
'normal_mean'
|
penalty
|
float | None
|
Cost of one extra change point. |
None
|
min_size
|
int
|
Minimum samples per segment. |
2
|
Returns:
| Type | Description |
|---|---|
list[int]
|
Sorted indices |
binseg ¤
binseg(
x: ndarray,
*,
cost: Cost = "normal_mean",
penalty: float | None = None,
min_size: int = 2
) -> list[int]
Change points by binary segmentation: fast (O(n log n)), approximate.
Splits a segment at its best point while the cost reduction exceeds
penalty, then recurses into both halves. Same arguments and return
value as :func:pelt; close changes may be merged or misplaced.