|
| 1 | +Continuous Difference-in-Differences |
| 2 | +===================================== |
| 3 | + |
| 4 | +Continuous DiD estimator for dose-response curves with continuous treatment intensity. |
| 5 | + |
| 6 | +This module implements the methodology from Callaway, Goodman-Bacon & Sant'Anna (2024), |
| 7 | +"Difference-in-Differences with a Continuous Treatment" (NBER WP 32117), which: |
| 8 | + |
| 9 | +1. **Estimates dose-response curves**: ATT(d) and ACRT(d) as functions of dose |
| 10 | +2. **Computes summary parameters**: Overall ATT (binarized) and ACRT aggregated across doses |
| 11 | +3. **Uses B-spline smoothing**: Flexible nonparametric estimation of dose-response functions |
| 12 | +4. **Supports multiplier bootstrap**: Valid inference with proper standard errors and CIs |
| 13 | + |
| 14 | +.. note:: |
| 15 | + |
| 16 | + **Identification assumptions.** The dose-response curves ATT(d) and ACRT(d), |
| 17 | + as well as ATT\ :sup:`glob` and ACRT\ :sup:`glob`, require the **Strong Parallel |
| 18 | + Trends (SPT)** assumption — that there is no selection into dose groups based on |
| 19 | + treatment effects. Under the weaker standard Parallel Trends (PT) assumption, |
| 20 | + only the binarized ATT\ :sup:`loc` (``overall_att``) is identified; it equals |
| 21 | + ATT\ :sup:`glob` only when SPT holds. See Callaway, Goodman-Bacon & Sant'Anna |
| 22 | + (2024), Assumptions 1–2. |
| 23 | + |
| 24 | +**When to use Continuous DiD:** |
| 25 | + |
| 26 | +- Treatment varies in **intensity or dose** across units (not just binary on/off) |
| 27 | +- You want to estimate how effects change with treatment dose |
| 28 | +- Staggered adoption with heterogeneous dose levels |
| 29 | +- You need the full dose-response curve, not just a single average effect |
| 30 | + |
| 31 | +**Data requirements:** |
| 32 | + |
| 33 | +- An **untreated group** (D = 0) must be present in the data |
| 34 | +- A **balanced panel** is required (all units observed in all time periods) |
| 35 | +- **Dose must be time-invariant** — each unit's dose is fixed across periods |
| 36 | + |
| 37 | +**Reference:** Callaway, B., Goodman-Bacon, A., & Sant'Anna, P. H. C. (2024). |
| 38 | +Difference-in-Differences with a Continuous Treatment. *NBER Working Paper* 32117. |
| 39 | +`<https://www.nber.org/papers/w32117>`_ |
| 40 | + |
| 41 | +.. module:: diff_diff.continuous_did |
| 42 | + |
| 43 | +ContinuousDiD |
| 44 | +-------------- |
| 45 | + |
| 46 | +Main estimator class for Continuous Difference-in-Differences. |
| 47 | + |
| 48 | +.. autoclass:: diff_diff.ContinuousDiD |
| 49 | + :members: |
| 50 | + :undoc-members: |
| 51 | + :show-inheritance: |
| 52 | + :inherited-members: |
| 53 | + |
| 54 | + .. rubric:: Methods |
| 55 | + |
| 56 | + .. autosummary:: |
| 57 | + |
| 58 | + ~ContinuousDiD.fit |
| 59 | + ~ContinuousDiD.get_params |
| 60 | + ~ContinuousDiD.set_params |
| 61 | + |
| 62 | +ContinuousDiDResults |
| 63 | +-------------------- |
| 64 | + |
| 65 | +Results container for Continuous DiD estimation. |
| 66 | + |
| 67 | +.. autoclass:: diff_diff.continuous_did_results.ContinuousDiDResults |
| 68 | + :members: |
| 69 | + :undoc-members: |
| 70 | + :show-inheritance: |
| 71 | + |
| 72 | + .. rubric:: Methods |
| 73 | + |
| 74 | + .. autosummary:: |
| 75 | + |
| 76 | + ~ContinuousDiDResults.summary |
| 77 | + ~ContinuousDiDResults.print_summary |
| 78 | + ~ContinuousDiDResults.to_dataframe |
| 79 | + |
| 80 | +DoseResponseCurve |
| 81 | +----------------- |
| 82 | + |
| 83 | +Dose-response curve container for ATT(d) or ACRT(d). |
| 84 | + |
| 85 | +.. autoclass:: diff_diff.continuous_did_results.DoseResponseCurve |
| 86 | + :members: |
| 87 | + :undoc-members: |
| 88 | + :show-inheritance: |
| 89 | + |
| 90 | + .. rubric:: Methods |
| 91 | + |
| 92 | + .. autosummary:: |
| 93 | + |
| 94 | + ~DoseResponseCurve.to_dataframe |
| 95 | + |
| 96 | +Example Usage |
| 97 | +------------- |
| 98 | + |
| 99 | +Basic usage:: |
| 100 | + |
| 101 | + from diff_diff import ContinuousDiD, generate_continuous_did_data |
| 102 | + |
| 103 | + data = generate_continuous_did_data(n_units=200, seed=42) |
| 104 | + |
| 105 | + est = ContinuousDiD(n_bootstrap=199, seed=42) |
| 106 | + results = est.fit(data, outcome='outcome', unit='unit', |
| 107 | + time='period', first_treat='first_treat', |
| 108 | + dose='dose', aggregate='dose') |
| 109 | + results.print_summary() |
| 110 | + |
| 111 | +Accessing dose-response curves:: |
| 112 | + |
| 113 | + # ATT(d) dose-response curve as DataFrame |
| 114 | + att_df = results.dose_response_att.to_dataframe() |
| 115 | + print(att_df[['dose', 'effect', 'se', 'p_value']]) |
| 116 | + |
| 117 | + # ACRT(d) dose-response curve |
| 118 | + acrt_df = results.dose_response_acrt.to_dataframe() |
| 119 | + |
| 120 | + # Overall summary parameters |
| 121 | + print(f"Overall ATT: {results.overall_att:.3f} (SE: {results.overall_att_se:.3f})") |
| 122 | + print(f"Overall ACRT: {results.overall_acrt:.3f} (SE: {results.overall_acrt_se:.3f})") |
| 123 | + |
| 124 | +Event study aggregation:: |
| 125 | + |
| 126 | + # Dynamic effects (binarized ATT by relative period) |
| 127 | + results_es = est.fit(data, outcome='outcome', unit='unit', |
| 128 | + time='period', first_treat='first_treat', |
| 129 | + dose='dose', aggregate='eventstudy') |
| 130 | + es_df = results_es.to_dataframe(level='event_study') |
| 131 | + |
| 132 | +Comparison with CallawaySantAnna |
| 133 | +-------------------------------- |
| 134 | + |
| 135 | +.. list-table:: |
| 136 | + :header-rows: 1 |
| 137 | + :widths: 20 40 40 |
| 138 | + |
| 139 | + * - Feature |
| 140 | + - ContinuousDiD |
| 141 | + - CallawaySantAnna |
| 142 | + * - Treatment type |
| 143 | + - Continuous dose / intensity |
| 144 | + - Binary (treated / not treated) |
| 145 | + * - Target parameter |
| 146 | + - ATT\ :sup:`loc` (PT); ATT(d), ACRT(d), ATT\ :sup:`glob`, ACRT\ :sup:`glob` (SPT) |
| 147 | + - ATT(g,t), aggregated ATT |
| 148 | + * - Smoothing |
| 149 | + - B-spline basis for dose-response |
| 150 | + - None (nonparametric group-time) |
| 151 | + * - Dose-response curve |
| 152 | + - Yes (full curve with CIs) |
| 153 | + - No |
| 154 | + * - Bootstrap |
| 155 | + - Multiplier bootstrap (optional) |
| 156 | + - Multiplier bootstrap (optional) |
| 157 | + * - Control group |
| 158 | + - never_treated / not_yet_treated |
| 159 | + - never_treated / not_yet_treated |
0 commit comments