find_outliers
find_outliers(x, [method="zscore"], [threshold=], [window=7])
Input: x, method, threshold, window · Output: no output
What it is
The indices of the samples a criterion flags, as a number vector (same shape of answer as find_peaks). x is a length-N number vector or Signal. method is a named string: "zscore", "modified_zscore", "iqr", "hampel". threshold (alias n_sigma) is a named number, defaulting per method — see below. window is a named odd integer, default 7, read only by method="hampel"; passing it to the others is an unread-keyword error rather than silently ignored.
Overloads
One call shape — this function is not overloaded.
| Code | Input | Output | Description |
find_outliers(x, [method="zscore"], [threshold=], [window=7]) | x number, vector, or Signalx is a length-N number vector or Signal.method string, optional (default "zscore")method is a named string: "zscore", "modified_zscore", "iqr", "hampel".threshold number, optionalthreshold (alias n_sigma) is a named number, defaulting per method — see below.window optional (default 7)window is a named odd integer, default 7, read only by method="hampel". | not documented yet | The indices of the samples a criterion flags, as a number vector (same shape of answer as find_peaks). |
Examples
From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.
y = [1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 100]
print(find_outliers(y, method = "modified_zscore")) # [10]
print(remove_outliers(y, method = "modified_zscore")) # the 100 is gone
print(replace_outliers(y, method = "modified_zscore")[10]) # 2 -- patched in place
drift = 0 to 40
drift[20] = drift[20] + 30
print(find_outliers(drift, method = "hampel", window = 7)) # [20]
print(find_outliers(drift, method = "zscore")) # [] -- global test cannot see it
[10] [1, 2, 3, 2, 1, 2, 3, 2, 1, 2] 2 [20] []
from noise
How it works
find_outliers/remove_outliers/replace_outliers(x, [method="zscore"], [threshold=], [window=7], [fill_method="linear"], [value=]) — one function per ANSWER (which samples / drop them / patch them), one method= kwarg for the criterion, following smooth's own shape rather than growing a function per variant. "zscore" |x-mean|/std > threshold (3) "modified_zscore" 0.6745|x-med|/MAD > threshold (3.5) "iqr" outside Q1/Q3 +- threshold*IQR (1.5) "hampel" the local, windowed test -- hampel's own criterion, shared with it rather than reimplemented. The default threshold is per-method on purpose: 3 sigma, 3.5 modified-z and 1.5 IQR are the conventional cutoffs for three DIFFERENT scales, and one shared number would silently make two of the three mean something nobody intends. window= is read only by method="hampel", the only criterion that has a window -- passing it to the others is an unread kwarg and errors, rather than being accepted and ignored. There is deliberately no count in the return value: the "how many" question is length(find_outliers(...)), which is the same number and available before committing to a transform, and that keeps the two transforms chainable (x.remove_outliers().fft()) instead of returning a record the next call cannot take.
From the note above this builtin in the interpreter, where the reasoning was written down as it was built.