statspai.causal_impact¶
causal_impact ¶
Causal Impact module for StatsPAI.
Estimates the causal effect of an intervention on a time series by constructing a synthetic counterfactual from control series using a structural time-series model.
Equivalent to Google's R CausalImpact package.
References
Brodersen, K.H., Gallusser, F., Koehler, J., Remy, N., and Scott, S.L. (2015). "Inferring Causal Impact Using Bayesian Structural Time-Series Models." Annals of Applied Statistics, 9(1), 247-274. [@brodersen2015inferring]
CausalImpactEstimator ¶
Causal Impact estimator using a structural time-series model.
Fits a regression + local-level (AR(1)) model on the
pre-intervention period, then forecasts the counterfactual into the
post-intervention period. The high-level :func:causal_impact
wrapper is the usual entry point; instantiate this class directly
only when you want to drive .fit() yourself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
Time-series data, one row per period. |
required |
y
|
str
|
Outcome (intervened) series. |
required |
time
|
str
|
Time column used for ordering. |
required |
intervention_time
|
Any
|
First post-intervention period (inclusive). |
required |
covariates
|
list of str
|
Control series unaffected by the intervention. |
None
|
alpha
|
float
|
Significance level for the credible intervals. |
0.05
|
n_seasons
|
int
|
Seasonal period, if any. |
None
|
Examples:
>>> import numpy as np
>>> import pandas as pd
>>> import statspai as sp
>>> rng = np.random.default_rng(0)
>>> n = 60
>>> week = np.arange(n)
>>> ad_spend = rng.normal(100, 5, size=n)
>>> sales = 2.0 * ad_spend + rng.normal(0, 3, size=n)
>>> sales[40:] += 15.0
>>> df = pd.DataFrame({'week': week, 'sales': sales,
... 'ad_spend': ad_spend})
>>> est = sp.CausalImpactEstimator(df, y='sales', time='week',
... intervention_time=40,
... covariates=['ad_spend'])
>>> result = est.fit()
>>> (est.n_pre, est.n_post)
(40, 20)
>>> bool(result.estimate > 0)
True
causal_impact ¶
causal_impact(data: DataFrame, y: str, time: str, intervention_time: Any, covariates: Optional[List[str]] = None, alpha: float = 0.05, n_seasons: Optional[int] = None) -> CausalResult
Estimate the causal impact of an intervention on a time series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
Time-series data (one row per time period). |
required |
y
|
str
|
Outcome variable (the series that was intervened upon). |
required |
time
|
str
|
Time column (used for ordering; can be int, date, etc.). |
required |
intervention_time
|
any
|
First period of the intervention (inclusive). |
required |
covariates
|
list of str
|
Control time series (not affected by the intervention). If None, uses a local-level model without covariates. |
None
|
alpha
|
float
|
Significance level for credible intervals. |
0.05
|
n_seasons
|
int
|
Seasonal period (e.g., 7 for weekly, 12 for monthly). |
None
|
Returns:
| Type | Description |
|---|---|
CausalResult
|
|
Examples:
Effect of an intervention introduced at week 40, recovered against a counterfactual built from an ad-spend control series:
>>> import numpy as np
>>> import pandas as pd
>>> import statspai as sp
>>> rng = np.random.default_rng(0)
>>> n = 60
>>> week = np.arange(n)
>>> ad_spend = rng.normal(100, 5, size=n)
>>> sales = 2.0 * ad_spend + rng.normal(0, 3, size=n)
>>> sales[40:] += 15.0 # intervention lifts sales from week 40
>>> df = pd.DataFrame({'week': week, 'sales': sales,
... 'ad_spend': ad_spend})
>>> result = sp.causal_impact(df, y='sales', time='week',
... intervention_time=40,
... covariates=['ad_spend'])
>>> result.n_obs
60
>>> bool(result.estimate > 0) # positive average impact recovered
True
References
brodersen2015inferring
impactplot ¶
impactplot(result: CausalResult, type: str = 'all', ax: Any = None, figsize: tuple[float, float] = (12, 9), title: Optional[str] = None) -> Any
Causal Impact visualization (Google-style 3-panel plot).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
CausalResult
|
Result from |
required |
type
|
str
|
'all': 3-panel (original + pointwise + cumulative). 'original': actual vs counterfactual. 'pointwise': pointwise causal effect. 'cumulative': cumulative effect. |
'all'
|
ax
|
matplotlib Axes
|
Only for single-panel types. |
None
|
figsize
|
tuple
|
|
(12, 9)
|
title
|
str
|
|
None
|
Returns:
| Type | Description |
|---|---|
(fig, ax) or (fig, axes)
|
|
Examples:
>>> import numpy as np
>>> import pandas as pd
>>> import matplotlib
>>> matplotlib.use('Agg')
>>> import statspai as sp
>>> rng = np.random.default_rng(0)
>>> n = 60
>>> week = np.arange(n)
>>> ad_spend = rng.normal(100, 5, size=n)
>>> sales = 2.0 * ad_spend + rng.normal(0, 3, size=n)
>>> sales[40:] += 15.0
>>> df = pd.DataFrame({'week': week, 'sales': sales,
... 'ad_spend': ad_spend})
>>> result = sp.causal_impact(df, y='sales', time='week',
... intervention_time=40,
... covariates=['ad_spend'])
>>> fig, axes = sp.impactplot(result, type='all')
>>> len(axes)
3
>>> fig.savefig('impact.png')