diff_diff.MultiPeriodDiD#

class diff_diff.MultiPeriodDiD[source]#

Bases: DifferenceInDifferences

Multi-Period Difference-in-Differences estimator.

Extends the standard DiD to handle multiple pre-treatment and post-treatment time periods, providing period-specific treatment effects as well as an aggregate average treatment effect.

Parameters:
  • robust (bool, default=True) – Legacy alias for vcov_type. robust=True maps to vcov_type="hc1"; robust=False maps to vcov_type="classical". Explicit vcov_type overrides robust unless the pair is contradictory (e.g. robust=False, vcov_type="hc2" raises).

  • cluster (str, optional) – Column name for cluster-robust standard errors. With vcov_type="hc1" dispatches to CR1 (Liang-Zeger). With vcov_type="hc2_bm" dispatches to CR2 cluster-robust SEs with Bell-McCaffrey Satterthwaite DOF on both per-period coefficients and the post-period-average ATT contrast (the latter via the new _compute_cr2_bm_contrast_dof helper in linalg.py; matches clubSandwich’s Wald_test(test="HTZ")$df_denom at atol=1e-10). Weighted CR2-BM (survey_design=) is a separate, still-gated path.

  • vcov_type ({"classical", "hc1", "hc2", "hc2_bm", "conley"}, optional) –

    Variance-covariance family. Defaults to the robust alias.

    • "classical": non-robust OLS SEs, sigma_hat^2 * (X'X)^{-1}.

    • "hc1": heteroskedasticity-robust HC1 with n/(n-k) adjustment (library default). With cluster=, uses CR1 (Liang-Zeger).

    • "hc2": leverage-corrected meat (one-way only). Errors with cluster=; use "hc2_bm" without cluster for Bell-McCaffrey.

    • "hc2_bm": one-way HC2 + Imbens-Kolesar (2016) Satterthwaite DOF per coefficient plus a contrast-aware DOF for the post-period-average ATT. With cluster=, dispatches to Pustejovsky-Tipton (2018) CR2 cluster-robust with a Bell-McCaffrey Satterthwaite contrast DOF on the post-period average (see cluster above for parity details). Weighted CR2-BM (survey_design=) is still gated.

    • "conley": Conley 1999 spatial-HAC sandwich via the panel block-decomposed form (matches R conleyreg with lag_cutoff > 0). Pass conley_coords=(lat_col, lon_col), conley_cutoff_km=<float>, and conley_lag_cutoff=<int> on the constructor; unit= must be supplied at fit-time. The sandwich sums within-period spatial pairs plus within-unit Bartlett serial pairs (lag=0 excluded to avoid double-counting); this is NOT a multiplicative product kernel. conley_time is auto-derived from the time column at fit-time and normalized to dense panel-period codes 0..T-1 so conley_lag_cutoff always counts panel periods (works for int / datetime64 / pd.Period / string encodings). Explicit cluster=<col> enables the combined spatial + cluster product kernel (Wave A #119; cluster must be constant within each unit across periods). Restrictions: survey_design= and inference="wild_bootstrap" raise on this path (Phase 5 / follow-up).

  • alpha (float, default=0.05) – Significance level for confidence intervals.

  • conley_coords – Constructor kwargs that take effect when vcov_type="conley". conley_coords is a (lat_col, lon_col) tuple of column names on data. conley_lag_cutoff is the within-unit Bartlett lag (non-negative int; 0 means within-period spatial only, no serial component).

  • conley_cutoff_km – Constructor kwargs that take effect when vcov_type="conley". conley_coords is a (lat_col, lon_col) tuple of column names on data. conley_lag_cutoff is the within-unit Bartlett lag (non-negative int; 0 means within-period spatial only, no serial component).

  • conley_metric – Constructor kwargs that take effect when vcov_type="conley". conley_coords is a (lat_col, lon_col) tuple of column names on data. conley_lag_cutoff is the within-unit Bartlett lag (non-negative int; 0 means within-period spatial only, no serial component).

  • conley_kernel – Constructor kwargs that take effect when vcov_type="conley". conley_coords is a (lat_col, lon_col) tuple of column names on data. conley_lag_cutoff is the within-unit Bartlett lag (non-negative int; 0 means within-period spatial only, no serial component).

  • conley_lag_cutoff – Constructor kwargs that take effect when vcov_type="conley". conley_coords is a (lat_col, lon_col) tuple of column names on data. conley_lag_cutoff is the within-unit Bartlett lag (non-negative int; 0 means within-period spatial only, no serial component).

results_#

Estimation results after calling fit().

Type:

MultiPeriodDiDResults

is_fitted_#

Whether the model has been fitted.

Type:

bool

Examples

Basic usage with multiple time periods:

>>> import pandas as pd
>>> from diff_diff import MultiPeriodDiD
>>>
>>> # Create sample panel data with 6 time periods
>>> # Periods 0-2 are pre-treatment, periods 3-5 are post-treatment
>>> data = create_panel_data()  # Your data
>>>
>>> # Fit the model
>>> did = MultiPeriodDiD()
>>> results = did.fit(
...     data,
...     outcome='sales',
...     treatment='treated',
...     time='period',
...     post_periods=[3, 4, 5]  # Specify which periods are post-treatment
... )
>>>
>>> # View period-specific effects
>>> for period, effect in results.period_effects.items():
...     print(f"Period {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
>>>
>>> # View average treatment effect
>>> print(f"Average ATT: {results.avg_att:.3f}")

Notes

The model estimates:

Y_it = α + β*D_i + Σ_t γ_t*Period_t + Σ_{t≠ref} δ_t*(D_i × 1{t}) + ε_it

Where: - D_i is the treatment indicator - Period_t are time period dummies (all non-reference periods) - D_i × 1{t} are treatment-by-period interactions (all non-reference) - δ_t are the period-specific treatment effects - The reference period (default: last pre-period) has δ_ref = 0 by construction

Pre-treatment δ_t test the parallel trends assumption (should be ≈ 0). Post-treatment δ_t estimate dynamic treatment effects. The average ATT is computed from post-treatment δ_t only.

Methods

__init__([robust, cluster, vcov_type, ...])

fit(data, outcome, treatment, time[, ...])

Fit the Multi-Period Difference-in-Differences model.

get_params()

Get estimator parameters (sklearn-compatible).

predict(data)

Predict outcomes using fitted model.

print_summary()

Print summary to stdout.

set_params(**params)

Set estimator parameters (sklearn-compatible).

summary()

Get summary of estimation results.

__init__(robust=True, cluster=None, vcov_type=None, alpha=0.05, inference='analytical', n_bootstrap=999, bootstrap_weights='rademacher', seed=None, rank_deficient_action='warn', conley_coords=None, conley_cutoff_km=None, conley_metric='haversine', conley_kernel='bartlett', conley_lag_cutoff=None)#
Parameters:
  • robust (bool)

  • cluster (str | None)

  • vcov_type (str | None)

  • alpha (float)

  • inference (str)

  • n_bootstrap (int)

  • bootstrap_weights (str)

  • seed (int | None)

  • rank_deficient_action (str)

  • conley_coords (Tuple[str, str] | None)

  • conley_cutoff_km (float | None)

  • conley_metric (str)

  • conley_kernel (str)

  • conley_lag_cutoff (int | None)

classmethod __new__(*args, **kwargs)#