diff_diff.ChangesInChanges#

class diff_diff.ChangesInChanges[source]#

Bases: object

Changes-in-Changes estimator (Athey & Imbens 2006) for the 2x2 design.

Estimates the ATT (eq. 36) and quantile treatment effects on the treated (eq. 18) by building the treated group’s counterfactual untreated outcome distribution F_10(F_00^{-1}(F_01(y))) (Theorem 3.1). Point estimates match qte::CiC() (R, v1.3.1) exactly; the empirical inverse CDF is the paper’s eq. (35)/(A.1) ceiling-order-statistic convention (R type-1).

Inference is bootstrap-only (n_bootstrap=0 disables it and reports NaN inference fields): panel mode resamples units with both periods together; repeated cross-section mode draws a pooled row resample. Standard errors are replicate SDs with symmetric normal-approximation intervals; results_.sup_t_crit carries qte’s sup-t critical value for uniform bands at a fixed 95% level (independent of alpha, matching qte).

Parameters:
  • quantiles (array-like, optional) – Quantile grid strictly inside (0, 1). Default: 0.05 to 0.95 in steps of 0.05 (matches qte’s probs).

  • n_bootstrap (int, default=200) – Bootstrap replicates. 0 disables inference (NaN se/t/p/CI).

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

  • panel (bool, default=False) – True when the same units are observed in both periods (requires unit= at fit time; enforces a balanced panel). Affects only the bootstrap resampling scheme - the point estimator uses the four marginal cell distributions either way.

  • seed (int, optional) – Seed for the bootstrap RNG (numpy.random.default_rng).

Notes

Quantile effects are point-identified only on the eq. (17) interior range (q_lower, q_upper); effects outside it keep their point estimates (qte parity) but report NaN inference with a warning. This guard applies to unconditional (no-covariate) fits only: with covariates the eq. (17) bounds are not the relevant objects (q_lower/q_upper are NaN) and a conditional support diagnostic replaces the unconditional one.

Covariates (covariates= at fit time, or trailing formula terms) port qte’s xformla branch exactly: linear quantile regressions of the outcome on the covariates within the control pre- and post-period cells on qte’s fixed internal 0.01-0.99 tau grid (99 points, not user-configurable), conditional-rank imputation per treated pre-period observation, and the same bootstrap schemes with every quantile regression refit inside each replicate. Covariates must be numeric (dummy-encode categoricals). Runtime note: a covariate fit solves roughly 2 x 99 x (1 + n_bootstrap) small linear programs (~40k at the default n_bootstrap=200) - typically tens of seconds at moderate cell sizes, the same cost profile as qte::CiC.

Additive random group-time shocks (random effects at the group x period level) BIAS the CiC estimator - unlike linear DiD, where they only complicate inference - and are not detectable in a 2x2 design (Athey & Imbens 2006, p. 476). With more than two groups/periods they are testable (Theorem 6.4), but that extension is deferred.

The full Melly-Santangelo (2015) covariate estimator (monotonized integrated-indicator CDFs, treated-post covariate integration, exchangeable bootstrap), discrete-outcome bounds, and analytical standard errors remain deferred and documented in docs/methodology/REGISTRY.md.

Methods

__init__([quantiles, n_bootstrap, alpha, ...])

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

Fit the CiC estimator on a 2x2 dataset.

get_params([deep])

Return constructor hyperparameters (raw values, round-trips __init__).

set_params(**params)

Set hyperparameters transactionally (a failing call mutates nothing).

__init__(quantiles=None, n_bootstrap=200, alpha=0.05, panel=False, seed=None)[source]#
Parameters:
classmethod __new__(*args, **kwargs)#