SyntheticDifferenceInDifferences#

class causalpy.experiments.synthetic_difference_in_differences.SyntheticDifferenceInDifferences[source]#

Bayesian Synthetic Difference-in-Differences experiment.

Combines the synthetic control method’s unit weighting with difference-in-differences time weighting. The treatment effect (tau) is computed analytically from the posterior weight distributions via the double-difference formula, rather than being estimated inside the MCMC model (cut-posterior formulation).

Parameters:
  • data (DataFrame) – A dataframe in wide format (columns = units, rows = time periods).

  • treatment_time (int | float | Timestamp) – The time when treatment occurred, should be in reference to the data index.

  • control_units (list[str]) – A list of control unit column names.

  • treated_units (list[str]) – A list of treated unit column names.

  • model (PyMCModel | RegressorMixin | None) – A SyntheticDifferenceInDifferencesWeightFitter instance. Defaults to SyntheticDifferenceInDifferencesWeightFitter.

  • **kwargs (dict) – Additional keyword arguments (currently unused).

Notes

Estimate extraction

The Bayesian weight model produces posterior draws of synthetic-control unit weights and pre-period time weights. For each draw, the class constructs treated-minus-synthetic gaps and evaluates the weighted double-difference analytically to obtain the scalar tau_posterior ATT; the effect is not read from a regression coefficient or obtained by population-standardized g-computation. The time-indexed post_impact consumed by effect_summary() is the post-period treated-minus-synthetic trajectory rather than this time-weighted scalar.

This implements Bayesian SDiD method. The model fits two weight modules via MCMC:

  • Unit weights (omega): balance control units against treated units in the pre-treatment period, similar to synthetic control.

  • Time weights (lambda): balance pre-treatment periods against post-treatment periods for control units.

The treatment effect is then computed analytically via the double-difference:

\[\tau = \bar{\Delta}_{\text{post}} - \boldsymbol{\lambda}^\top \boldsymbol{\Delta}_{\text{pre}}\]

where \(\Delta_t = y_{\text{tr},t} - (\omega_0 + \boldsymbol{\omega}^\top \mathbf{Y}_{\text{co},t})\) is the gap between the observed treated outcome and the synthetic control at time t.

References

Examples

>>> import causalpy as cp
>>> df = cp.load_data("sc")
>>> treatment_time = 70
>>> result = cp.SyntheticDifferenceInDifferences(
...     df,
...     treatment_time,
...     control_units=["a", "b", "c", "d", "e", "f", "g"],
...     treated_units=["actual"],
...     model=cp.pymc_models.SyntheticDifferenceInDifferencesWeightFitter(
...         sample_kwargs={
...             "tune": 20,
...             "draws": 20,
...             "chains": 2,
...             "cores": 2,
...             "progressbar": False,
...         }
...     ),
... )

Methods

SyntheticDifferenceInDifferences.algorithm()

Run the SDiD algorithm: fit weight modules, compute tau analytically.

SyntheticDifferenceInDifferences.effect_summary(*)

Generate a decision-ready summary of causal effects for SDiD.

SyntheticDifferenceInDifferences.fit(*args, ...)

Fit the underlying model.

SyntheticDifferenceInDifferences.generate_report(*)

Generate a self-contained HTML report for this experiment.

SyntheticDifferenceInDifferences.get_plot_data(...)

Recover the data of an experiment along with the prediction and causal impact information.

SyntheticDifferenceInDifferences.input_validation(...)

Validate the input data for correctness.

SyntheticDifferenceInDifferences.plot(*[, ...])

Plot SDiD results: counterfactual, period impact, and cumulative impact.

SyntheticDifferenceInDifferences.print_coefficients([...])

Ask the model to print its coefficients.

SyntheticDifferenceInDifferences.set_maketables_options(*)

Set optional maketables rendering options for this experiment.

SyntheticDifferenceInDifferences.summary([...])

Print summary of main results.

Attributes

datapost

Data from on or after the treatment time (inclusive).

datapre

Data from before the treatment time (exclusive).

idata

Return fitted InferenceData when the model backend supports it.

supports_bayes

supports_ols

supports_pymc_forecast

labels

data

__init__(data, treatment_time, control_units, treated_units, model=None, **kwargs)[source]#
Parameters:
Return type:

None

classmethod __new__(*args, **kwargs)#