Skip to content

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

fit

fit() -> CausalResult

Fit the structural time-series model and estimate causal impact.

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 causal_impact().

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')