diff_diff.ContinuousDiD#
- class diff_diff.ContinuousDiD[source]#
Bases:
objectContinuous Difference-in-Differences estimator.
Implements the methodology from Callaway, Goodman-Bacon & Sant’Anna (2024) for estimating dose-response curves when treatment has a continuous intensity.
- Parameters:
degree (int, default=3) – B-spline degree (3 = cubic).
num_knots (int, default=0) – Number of interior knots for the B-spline basis.
dvals (array-like, optional) – Custom dose evaluation grid. If None, uses quantile-based default.
control_group (str, default="never_treated") –
"never_treated","not_yet_treated", or"lowest_dose"."lowest_dose"implements Remark 3.1 (CGBS 2024) for settings with no never-treated / zero-dose units (P(D=0) = 0): the lowest-dose groupd_Lbecomes the comparison and the estimand isATT(d) − ATT(d_L). Requires a genuine lowest-dose group (>= 2units atd_L, i.e.P(D=d_L) > 0) and no never-treated units present. Single-cohort only (multi-cohort andcovariates=raiseNotImplementedError).anticipation (int, default=0) – Number of periods of treatment anticipation.
base_period (str, default="varying") –
"varying"or"universal".alpha (float, default=0.05) – Significance level for confidence intervals.
n_bootstrap (int, default=0) – Number of multiplier bootstrap iterations. 0 for analytical SEs only.
bootstrap_weights (str, default="rademacher") – Bootstrap weight type:
"rademacher","mammen", or"webb".seed (int, optional) – Random seed for reproducibility.
rank_deficient_action (str, default="warn") – Action for rank-deficient B-spline OLS:
"warn","error", or"silent".covariates (list of str, optional) – Column names of covariates for conditional parallel trends (
E[ΔY(0) | D=d, X] = E[ΔY(0) | D=0, X]). WhenNone(default) the estimator uses unconditional parallel trends. Covariates enter through a covariate-adjusted per-cell control counterfactual (seeestimation_method). Covariates are read from the base period of each(g, t)comparison. Not currently composable withsurvey_design=(raisesNotImplementedError).estimation_method (str, default="dr") – Covariate-adjustment method (only used when
covariatesis set):"reg"(outcome regression) or"dr"(doubly-robust, the default)."ipw"is not supported on the dose / event-study aggregation — pure IPW’s covariate adjustment is a single scalar level shift, so it cannot adjust the dose-response shape (ACRT(d) would be identical to the unconditional fit); it raisesNotImplementedError.reganddrshare the dose-response shape and ACRT(d);drdiffers only in theoverall_att/ ATT(d) level and in its doubly-robust standard errors.pscore_trim (float, default=0.01) – Propensity-score trimming bound for the
drpath (scores clipped to[pscore_trim, 1 - pscore_trim]).epv_threshold (float, default=10.0) – Events-per-variable threshold for the
drpropensity logit diagnostics.pscore_fallback (str, default="error") – Action when
drpropensity estimation raises (the logit IRLS fails with aLinAlgError/ValueError, e.g. perfect separation or rank deficiency):"error"(re-raise — the default, fail-closed so a dr fit never silently degrades to a non-DR estimate) or"unconditional"(fall back to an unconditional propensity with a warning; the affected cells are then reg-like — use only when you knowingly accept that). Note: low events-per-variable emits a diagnostic warning but does not itself trigger the fallback.treatment_type (str, default="continuous") – Dose-response model:
"continuous"(B-spline sieve, the default) or"discrete"(saturated per-dose-level regression, CGBS 2024 Eq. 4.1). On the discrete path each distinct dose level gets its own effect coefficient —ATT(d_j) = mean_{D=d_j}(ΔY) − control(a per-level 2×2 DiD) — andACRT(d_j)is the paper’s backward finite difference on the grid{0, d_1, ..., d_J}(ACRT(d_1) = ATT(d_1)/d_1, so a binary doseD in {0, 1}givesACRT = ATT). It composes withcovariatesandsurvey_designand reduces to the per-level 2×2 DiD standard error. Multi-cohort fits must share the same dose support across cohorts (elseNotImplementedError); an off-supportdvalsvalue raisesValueError.
Examples
>>> from diff_diff import ContinuousDiD, generate_continuous_did_data >>> data = generate_continuous_did_data(n_units=200, seed=42) >>> est = ContinuousDiD(n_bootstrap=199, seed=42) >>> results = est.fit(data, outcome="outcome", unit="unit", ... time="period", first_treat="first_treat", ... dose="dose", aggregate="dose") >>> results.overall_att
Methods
__init__([degree, num_knots, dvals, ...])fit(data, outcome, unit, time, first_treat, dose)Fit the continuous DiD estimator.
get_params()Return estimator parameters as a dictionary.
set_params(**params)Set estimator parameters and return self.
- __init__(degree=3, num_knots=0, dvals=None, control_group='never_treated', anticipation=0, base_period='varying', alpha=0.05, n_bootstrap=0, bootstrap_weights='rademacher', seed=None, rank_deficient_action='warn', covariates=None, estimation_method='dr', pscore_trim=0.01, epv_threshold=10.0, pscore_fallback='error', treatment_type='continuous')[source]#
- Parameters:
degree (int)
num_knots (int)
dvals (ndarray | None)
control_group (str)
anticipation (int)
base_period (str)
alpha (float)
n_bootstrap (int)
bootstrap_weights (str)
seed (int | None)
rank_deficient_action (str)
estimation_method (str)
pscore_trim (float)
epv_threshold (float)
pscore_fallback (str)
treatment_type (str)
- classmethod __new__(*args, **kwargs)#