API reference
The public API is the RegimeSHAPAnalyzer class plus the module-level functions it builds on.
RegimeSHAPAnalyzer
- class regime_shap.core.RegimeSHAPAnalyzer(model, X, regimes, *, date_column=None, small_sample_threshold=10, moderate_threshold=0.3, stable_threshold=0.6, random_state=42)[source]
Regime-aware SHAP feature-importance stability analysis for a tree model.
Supported models are tree-based (XGBoost, LightGBM, or scikit-learn tree ensembles), computed through
shap.TreeExplainer. This is deliberate: TreeExplainer is exact and fast, which is what makes the bootstrap confidence intervals feasible, since they recompute SHAP many times per regime. The stability methodology itself is model-agnostic (everything downstream operates on SHAP arrays, not the model), so support for other model types via pluggable explainers is a possible future extension, with the caveat that the bootstrap becomes expensive and approximate for non-tree models.- Parameters:
model (object)
X (pd.DataFrame)
regimes (object)
date_column (str | None)
small_sample_threshold (int)
moderate_threshold (float)
stable_threshold (float)
random_state (int)
- global_importance()[source]
Global mean absolute SHAP per feature, most important first.
- Return type:
Series
- per_regime_rankings()[source]
Feature-by-regime importance rankings (1 = most important).
- Return type:
DataFrame
- sample_sizes()[source]
Per-regime observation counts with the small-sample flag.
- Return type:
DataFrame
- stability_matrix()[source]
Regime-by-regime Spearman correlation of the feature rankings.
- Return type:
DataFrame
- stability_classified()[source]
Every regime pair with its Spearman rho, Akoglu band, and small-regime flag.
- Return type:
DataFrame
- bootstrap_cis(*, n_bootstrap=1000)[source]
Bootstrap confidence intervals for every regime pair involving a small regime.
- Parameters:
n_bootstrap (int) – Number of bootstrap resamples per regime.
- Returns:
A DataFrame of
regime_a,regime_b,ci_lower,ci_upper, andeffective_n(the smaller regime’s size), one row per pair that involves a small-sample regime. Empty if no regime is small.- Return type:
DataFrame
- plot_global(**kwargs)[source]
Global importance bar chart (see
plots.plot_global_importance).- Return type:
Figure
- plot_per_regime(**kwargs)[source]
Per-regime importance heatmap (see
plots.plot_per_regime_importance).- Return type:
Figure
- plot_stability(**kwargs)[source]
Stability heatmap, with the small regimes flagged and the analyzer’s bands.
- Return type:
Figure
regime_shap.breaks
Turn regime specifications into per-row regime labels.
Per-row labels are the package’s internal representation: a label for every row of the feature matrix, saying which regime that row belongs to. Users can supply labels directly (the most general, domain-agnostic form) or, for date-indexed data, give date ranges as a list of (start, end) tuples or a {label: (start, end)} dict, which the adapters here convert to per-row labels.
Optionally, when the user has no regimes in mind, detect_breaks wraps the
ruptures change-point library to propose break points from a series;
ruptures is an optional dependency (install with the detection extra).
- regime_shap.breaks.regimes_to_labels(X, regimes, *, date_column=None)[source]
Resolve any accepted regime specification into a per-row label Series.
- Parameters:
X (DataFrame) – The feature matrix whose rows are being labelled.
regimes (object) – One of three forms: - a per-row sequence of labels, length
len(X)(most general); - a list of(start, end)date ranges (labelled by position); - a{label: (start, end)}mapping. The date-range forms requireXto be datetime-indexed or to have adate_column.date_column (str | None) – Name of a datetime column to use instead of the index for the date-range forms. Ignored for per-row labels.
- Returns:
A Series of regime labels aligned to
X(same length and index).- Raises:
ValueError – If a per-row sequence has the wrong length, if a date-range form is given without usable dates, or if a row falls outside every supplied range.
- Return type:
Series
- regime_shap.breaks.detect_breaks(series, *, n_breaks=3, model='l2')[source]
Propose change-point positions in a 1D series using ruptures (optional dependency).
- Parameters:
series (Series) – The 1D series to search for structural breaks.
n_breaks (int) – Number of break points to return (uses ruptures’ Dynp).
model (str) – The ruptures cost model (“l2”, “l1”, “rbf”, …).
- Returns:
A list of break-point row positions (integer indices into
series), excluding the final endpoint.- Raises:
ImportError – If ruptures is not installed (pip install regime-shap[detection]).
- Return type:
list
regime_shap.compare
Per-regime SHAP feature importance and rankings.
Given SHAP values and a per-row regime label, this computes, within each regime, the mean absolute SHAP value per feature (that regime’s feature importance) and the resulting importance ranking. It also reports each regime’s sample size and flags small samples, whose rankings carry more uncertainty. The functions operate on plain arrays, not a fitted model, so they are model-agnostic and cheap to test.
- regime_shap.compare.per_regime_importance(shap_values, feature_names, labels)[source]
Mean absolute SHAP value per feature, within each regime.
- Parameters:
shap_values (ndarray) – A 2D array of SHAP values, rows by features, aligned to the rows the labels describe.
feature_names (Sequence[str]) – Column names for the features, length must match the number of SHAP columns.
labels (Series) – A per-row regime label for each row of
shap_values.
- Returns:
A DataFrame indexed by feature, one column per regime (in first- appearance order), holding the regime’s mean absolute SHAP per feature.
- Raises:
ValueError – If shap_values is not 2D, if the lengths of labels or feature_names do not match, or if any regime has fewer than two observations (a single row cannot give a meaningful importance).
- Return type:
DataFrame
- regime_shap.compare.per_regime_rankings(importance)[source]
Rank features within each regime, 1 being the most important.
- Parameters:
importance (DataFrame) – A feature-by-regime DataFrame of mean absolute SHAP, as returned by
per_regime_importance().- Returns:
A DataFrame of the same shape holding ranks per regime; tied features share the average of the ranks they span.
- Return type:
DataFrame
- regime_shap.compare.regime_sample_sizes(labels, *, small_sample_threshold=10)[source]
Per-regime observation counts with a small-sample flag.
- Parameters:
labels (Series) – A per-row regime label.
small_sample_threshold (int) – Regimes with fewer observations than this are flagged; their rankings should be read with the bootstrap confidence intervals rather than at face value.
- Returns:
regime,n_observations, andsmall_sample(bool).- Return type:
A DataFrame with one row per regime
regime_shap.stability
Cross-regime stability of SHAP feature-importance rankings.
The question this module answers: do the features the model leans on stay the
same across regimes, or do they reshuffle? Two regimes’ feature rankings are
compared with Spearman rank correlation (rho): 1 means identical orderings, -1
reversed, near 0 unrelated. pairwise_spearman_matrix builds the full
regime-by-regime table, and classify_stability labels a rho using the
Akoglu (2018) bands.
Small regimes give noisy rankings, so bootstrap_rankings resamples a
regime’s rows with replacement and recomputes the SHAP rankings each time, and
bootstrap_spearman_ci turns those into a confidence interval on rho, the
honest uncertainty a handful of observations carries rather than a single
falsely precise number. Rankings, not raw SHAP magnitudes, are compared, so the
result is not confounded by volatility differences between regimes.
Akoglu, H. (2018) ‘User’s guide to correlation coefficients’, Turkish Journal of Emergency Medicine, 18(3), pp. 91-93.
- regime_shap.stability.pairwise_spearman_matrix(rankings)[source]
Regime-by-regime Spearman correlation of the per-regime feature rankings.
- Parameters:
rankings (DataFrame) – A feature-by-regime DataFrame of ranks, as returned by
compare.per_regime_rankings.- Returns:
A square regime-by-regime DataFrame of Spearman rho, symmetric with a unit diagonal.
- Return type:
DataFrame
- regime_shap.stability.classify_stability(rho, *, moderate_threshold=0.3, stable_threshold=0.6)[source]
Label a Spearman rho by the Akoglu (2018) bands.
- Parameters:
rho (float) – A Spearman rank correlation.
moderate_threshold (float) – Upper edge of the unstable band (default 0.3).
stable_threshold (float) – Upper edge of the moderate band (default 0.6).
- Returns:
“stable” when rho > stable_threshold, “moderately stable” when moderate_threshold < rho <= stable_threshold, else “unstable”.
- Return type:
str
- regime_shap.stability.bootstrap_rankings(model, X_regime, *, n_bootstrap=1000, random_state=42)[source]
Bootstrap the SHAP feature rankings within one regime.
Resamples the regime’s rows with replacement
n_bootstraptimes, and for each resample recomputes TreeSHAP and ranks the features by mean absolute SHAP. Exploratory: this quantifies the uncertainty a small regime’s ranking already has, it does not remove it.- Parameters:
model (object) – A fitted tree model compatible with
shap.TreeExplainer. The explainer is recomputed once per resample, so its speed matters here; this exact, fast path is the reason the package is tree-only for now.X_regime (DataFrame) – The feature rows belonging to one regime.
n_bootstrap (int) – Number of resamples.
random_state (int) – Seed, so the result is reproducible.
- Returns:
An
(n_bootstrap, n_features)array of rankings, one row per resample.- Warns:
If the regime has fewer than ``MIN_BOOTSTRAP_OBS`` rows, the CI derived
from these rankings will be unreliable.
- Return type:
ndarray
- regime_shap.stability.bootstrap_spearman_ci(rankings_a, rankings_b, *, n_bootstrap=1000, ci=0.95)[source]
Confidence interval for Spearman rho between two regimes’ bootstrap rankings.
Pairs resample
iof one regime with resampleiof the other, computes rho for each pair, and returns the requested percentile interval of that distribution. For a pair involving a small regime this interval is often wide, which honestly reflects the uncertainty already present.- Parameters:
rankings_a (ndarray) – An
(n_bootstrap, n_features)array frombootstrap_rankings.rankings_b (ndarray) – The other regime’s array of the same shape.
n_bootstrap (int) – Cap on the number of paired draws used.
ci (float) – Confidence level (default 0.95 for a 95% interval).
- Returns:
A
(lower, upper)tuple of rho at the interval’s edges.- Return type:
tuple[float, float]
regime_shap.plots
Figures for regime-aware SHAP analysis.
Each function returns a matplotlib Figure; the caller saves or displays it. The figures are model- and domain-agnostic, they take the importance and stability tables the other modules produce, not any project-specific data. The stability heatmap colours cells by the Akoglu (2018) bands and can flag small-sample regimes so a reader does not over-read their rows.
- regime_shap.plots.plot_global_importance(importance, *, title='Global SHAP feature importance')[source]
Horizontal bar chart of global mean absolute SHAP per feature.
- Parameters:
importance (Series) – A Series of mean absolute SHAP indexed by feature.
title (str) – The figure title.
- Returns:
A matplotlib Figure, most-important feature at the top.
- Return type:
Figure
- regime_shap.plots.plot_per_regime_importance(importance, *, title='Per-regime SHAP feature importance')[source]
Heatmap of mean absolute SHAP per feature (rows) within each regime (columns).
- Parameters:
importance (DataFrame) – A feature-by-regime DataFrame of mean absolute SHAP.
title (str) – The figure title.
- Returns:
A matplotlib Figure with a colour bar.
- Return type:
Figure
- regime_shap.plots.plot_stability_heatmap(matrix, *, small_regimes=None, moderate_threshold=0.3, stable_threshold=0.6, title='SHAP ranking stability across regimes (Spearman rho)')[source]
Regime-by-regime Spearman heatmap coloured by the Akoglu (2018) bands.
- Parameters:
matrix (DataFrame) – A square regime-by-regime DataFrame of Spearman rho.
small_regimes (Set[str] | None) – Regime labels to flag with an asterisk (small samples, whose rows should be read with the bootstrap confidence intervals).
moderate_threshold (float) – Upper edge of the unstable band (default 0.3).
stable_threshold (float) – Upper edge of the moderate band (default 0.6).
title (str) – The figure title.
- Returns:
cells coloured red (unstable), orange (moderate), or green (stable), annotated with rho to two decimals.
- Return type:
A matplotlib Figure
regime_shap.report
Assemble the regime-aware SHAP results into shareable reports.
The analysis produces a handful of tables (global importance, per-regime
rankings, the stability matrix and its band classifications, sample sizes, and
any bootstrap confidence intervals). This module turns that collection into a
self-contained HTML report as the headline output, and exposes the same tables
as a plain dictionary and as CSV files so the results stay machine-readable.
Callers pass a mapping of {name: table}; the module does not assume any
particular set of tables, so it stays general.
- regime_shap.report.to_dict(tables)[source]
Return the result tables as JSON-serialisable nested dicts.
- Parameters:
tables (Mapping[str, DataFrame | Series]) – A mapping of table name to DataFrame or Series.
- Returns:
A dict keyed by table name; each DataFrame becomes a
{column: {index: value}}dict and each Series an{index: value}dict.- Return type:
dict
- regime_shap.report.save_csv(tables, output_dir)[source]
Write each table to
output_dir/<name>.csv.- Parameters:
tables (Mapping[str, DataFrame | Series]) – A mapping of table name to DataFrame or Series.
output_dir (str | Path) – Directory to write into; created if it does not exist.
- Returns:
The list of written file paths, in the order of
tables.- Return type:
list[Path]
- regime_shap.report.to_html(tables, *, title='regime-shap stability report', notes=None)[source]
Render the tables as a single self-contained HTML report.
- Parameters:
tables (Mapping[str, DataFrame | Series]) – A mapping of table name to DataFrame or Series, rendered in order under headings.
title (str) – The page and top heading title.
notes (list[str] | None) – Optional caveats shown near the top, for example that small regimes should be read with their bootstrap confidence intervals.
- Returns:
A complete HTML document as a string.
- Return type:
str