diff-diff 2.2.1__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {diff_diff-2.2.1 → diff_diff-2.3.0}/PKG-INFO +113 -2
- {diff_diff-2.2.1 → diff_diff-2.3.0}/README.md +111 -1
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/__init__.py +11 -1
- diff_diff-2.3.0/diff_diff/imputation.py +2480 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/twfe.py +39 -8
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/visualization.py +4 -2
- {diff_diff-2.2.1 → diff_diff-2.3.0}/pyproject.toml +2 -1
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/Cargo.lock +3 -3
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/Cargo.toml +1 -1
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/_backend.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/bacon.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/datasets.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/diagnostics.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/estimators.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/honest_did.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/linalg.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/power.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/prep.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/prep_dgp.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/pretrends.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/results.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/staggered.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/staggered_aggregation.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/staggered_bootstrap.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/staggered_results.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/sun_abraham.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/synthetic_did.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/triple_diff.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/trop.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/diff_diff/utils.py +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/src/bootstrap.rs +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/src/lib.rs +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/src/linalg.rs +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/src/trop.rs +0 -0
- {diff_diff-2.2.1 → diff_diff-2.3.0}/rust/src/weights.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diff-diff
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: Intended Audience :: Science/Research
|
|
6
6
|
Classifier: Operating System :: OS Independent
|
|
@@ -14,6 +14,7 @@ Requires-Dist: numpy>=1.20.0
|
|
|
14
14
|
Requires-Dist: pandas>=1.3.0
|
|
15
15
|
Requires-Dist: scipy>=1.7.0
|
|
16
16
|
Requires-Dist: pytest>=7.0 ; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest-xdist>=3.0 ; extra == 'dev'
|
|
17
18
|
Requires-Dist: pytest-cov>=4.0 ; extra == 'dev'
|
|
18
19
|
Requires-Dist: black>=23.0 ; extra == 'dev'
|
|
19
20
|
Requires-Dist: ruff>=0.1.0 ; extra == 'dev'
|
|
@@ -106,7 +107,7 @@ Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
|
|
|
106
107
|
- **Wild cluster bootstrap**: Valid inference with few clusters (<50) using Rademacher, Webb, or Mammen weights
|
|
107
108
|
- **Panel data support**: Two-way fixed effects estimator for panel designs
|
|
108
109
|
- **Multi-period analysis**: Event-study style DiD with period-specific treatment effects
|
|
109
|
-
- **Staggered adoption**: Callaway-Sant'Anna (2021)
|
|
110
|
+
- **Staggered adoption**: Callaway-Sant'Anna (2021), Sun-Abraham (2021), and Borusyak-Jaravel-Spiess (2024) imputation estimators for heterogeneous treatment timing
|
|
110
111
|
- **Triple Difference (DDD)**: Ortiz-Villavicencio & Sant'Anna (2025) estimators with proper covariate handling
|
|
111
112
|
- **Synthetic DiD**: Combined DiD with synthetic control for improved robustness
|
|
112
113
|
- **Triply Robust Panel (TROP)**: Factor-adjusted DiD with synthetic weights (Athey et al. 2025)
|
|
@@ -915,6 +916,54 @@ print(f"Sun-Abraham ATT: {sa_results.overall_att:.3f}")
|
|
|
915
916
|
# If results differ substantially, investigate heterogeneity
|
|
916
917
|
```
|
|
917
918
|
|
|
919
|
+
### Borusyak-Jaravel-Spiess Imputation Estimator
|
|
920
|
+
|
|
921
|
+
The Borusyak et al. (2024) imputation estimator is the **efficient** estimator for staggered DiD under parallel trends, producing ~50% shorter confidence intervals than Callaway-Sant'Anna and 2-3.5x shorter than Sun-Abraham under homogeneous treatment effects.
|
|
922
|
+
|
|
923
|
+
```python
|
|
924
|
+
from diff_diff import ImputationDiD, imputation_did
|
|
925
|
+
|
|
926
|
+
# Basic usage
|
|
927
|
+
est = ImputationDiD()
|
|
928
|
+
results = est.fit(data, outcome='outcome', unit='unit',
|
|
929
|
+
time='period', first_treat='first_treat')
|
|
930
|
+
results.print_summary()
|
|
931
|
+
|
|
932
|
+
# Event study
|
|
933
|
+
results = est.fit(data, outcome='outcome', unit='unit',
|
|
934
|
+
time='period', first_treat='first_treat',
|
|
935
|
+
aggregate='event_study')
|
|
936
|
+
|
|
937
|
+
# Pre-trend test (Equation 9)
|
|
938
|
+
pt = results.pretrend_test(n_leads=3)
|
|
939
|
+
print(f"F-stat: {pt['f_stat']:.3f}, p-value: {pt['p_value']:.4f}")
|
|
940
|
+
|
|
941
|
+
# Convenience function
|
|
942
|
+
results = imputation_did(data, 'outcome', 'unit', 'period', 'first_treat',
|
|
943
|
+
aggregate='all')
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
```python
|
|
947
|
+
ImputationDiD(
|
|
948
|
+
anticipation=0, # Number of anticipation periods
|
|
949
|
+
alpha=0.05, # Significance level
|
|
950
|
+
cluster=None, # Cluster variable (defaults to unit)
|
|
951
|
+
n_bootstrap=0, # Bootstrap iterations (0=analytical inference)
|
|
952
|
+
seed=None, # Random seed
|
|
953
|
+
horizon_max=None, # Max event-study horizon
|
|
954
|
+
aux_partition="cohort_horizon", # Variance partition: "cohort_horizon", "cohort", "horizon"
|
|
955
|
+
)
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
**When to use Imputation DiD vs Callaway-Sant'Anna:**
|
|
959
|
+
|
|
960
|
+
| Aspect | Imputation DiD | Callaway-Sant'Anna |
|
|
961
|
+
|--------|---------------|-------------------|
|
|
962
|
+
| Efficiency | Most efficient under homogeneous effects | Less efficient but more robust to heterogeneity |
|
|
963
|
+
| Control group | Always uses all untreated obs | Choice of never-treated or not-yet-treated |
|
|
964
|
+
| Inference | Conservative variance (Theorem 3) | Multiplier bootstrap |
|
|
965
|
+
| Pre-trends | Built-in F-test (Equation 9) | Separate testing |
|
|
966
|
+
|
|
918
967
|
### Triple Difference (DDD)
|
|
919
968
|
|
|
920
969
|
Triple Difference (DDD) is used when treatment requires satisfying two criteria: belonging to a treated **group** AND being in an eligible **partition**. The `TripleDifference` class implements the methodology from Ortiz-Villavicencio & Sant'Anna (2025), which correctly handles covariate adjustment (unlike naive implementations).
|
|
@@ -2036,6 +2085,60 @@ SunAbraham(
|
|
|
2036
2085
|
| `print_summary(alpha)` | Print summary to stdout |
|
|
2037
2086
|
| `to_dataframe(level)` | Convert to DataFrame ('event_study' or 'cohort') |
|
|
2038
2087
|
|
|
2088
|
+
### ImputationDiD
|
|
2089
|
+
|
|
2090
|
+
```python
|
|
2091
|
+
ImputationDiD(
|
|
2092
|
+
anticipation=0, # Periods of anticipation effects
|
|
2093
|
+
alpha=0.05, # Significance level for CIs
|
|
2094
|
+
cluster=None, # Column for cluster-robust SEs
|
|
2095
|
+
n_bootstrap=0, # Bootstrap iterations (0 = analytical)
|
|
2096
|
+
seed=None, # Random seed
|
|
2097
|
+
rank_deficient_action='warn', # 'warn', 'error', or 'silent'
|
|
2098
|
+
horizon_max=None, # Max event-study horizon
|
|
2099
|
+
aux_partition='cohort_horizon', # Variance partition
|
|
2100
|
+
)
|
|
2101
|
+
```
|
|
2102
|
+
|
|
2103
|
+
**fit() Parameters:**
|
|
2104
|
+
|
|
2105
|
+
| Parameter | Type | Description |
|
|
2106
|
+
|-----------|------|-------------|
|
|
2107
|
+
| `data` | DataFrame | Panel data |
|
|
2108
|
+
| `outcome` | str | Outcome variable column name |
|
|
2109
|
+
| `unit` | str | Unit identifier column |
|
|
2110
|
+
| `time` | str | Time period column |
|
|
2111
|
+
| `first_treat` | str | First treatment period column (0 for never-treated) |
|
|
2112
|
+
| `covariates` | list | Covariate column names |
|
|
2113
|
+
| `aggregate` | str | Aggregation: None, "event_study", "group", "all" |
|
|
2114
|
+
| `balance_e` | int | Balance event study to this many pre-treatment periods |
|
|
2115
|
+
|
|
2116
|
+
### ImputationDiDResults
|
|
2117
|
+
|
|
2118
|
+
**Attributes:**
|
|
2119
|
+
|
|
2120
|
+
| Attribute | Description |
|
|
2121
|
+
|-----------|-------------|
|
|
2122
|
+
| `overall_att` | Overall average treatment effect on the treated |
|
|
2123
|
+
| `overall_se` | Standard error (conservative, Theorem 3) |
|
|
2124
|
+
| `overall_t_stat` | T-statistic |
|
|
2125
|
+
| `overall_p_value` | P-value for H0: ATT = 0 |
|
|
2126
|
+
| `overall_conf_int` | Confidence interval |
|
|
2127
|
+
| `event_study_effects` | Dict of relative time -> effect dict (if `aggregate='event_study'` or `'all'`) |
|
|
2128
|
+
| `group_effects` | Dict of cohort -> effect dict (if `aggregate='group'` or `'all'`) |
|
|
2129
|
+
| `treatment_effects` | DataFrame of unit-level imputed treatment effects |
|
|
2130
|
+
| `n_treated_obs` | Number of treated observations |
|
|
2131
|
+
| `n_untreated_obs` | Number of untreated observations |
|
|
2132
|
+
|
|
2133
|
+
**Methods:**
|
|
2134
|
+
|
|
2135
|
+
| Method | Description |
|
|
2136
|
+
|--------|-------------|
|
|
2137
|
+
| `summary(alpha)` | Get formatted summary string |
|
|
2138
|
+
| `print_summary(alpha)` | Print summary to stdout |
|
|
2139
|
+
| `to_dataframe(level)` | Convert to DataFrame ('observation', 'event_study', 'group') |
|
|
2140
|
+
| `pretrend_test(n_leads)` | Run pre-trend F-test (Equation 9) |
|
|
2141
|
+
|
|
2039
2142
|
### TripleDifference
|
|
2040
2143
|
|
|
2041
2144
|
```python
|
|
@@ -2500,6 +2603,14 @@ The `HonestDiD` module implements sensitivity analysis methods for relaxing the
|
|
|
2500
2603
|
|
|
2501
2604
|
### Multi-Period and Staggered Adoption
|
|
2502
2605
|
|
|
2606
|
+
- **Borusyak, K., Jaravel, X., & Spiess, J. (2024).** "Revisiting Event-Study Designs: Robust and Efficient Estimation." *Review of Economic Studies*, 91(6), 3253-3285. [https://doi.org/10.1093/restud/rdae007](https://doi.org/10.1093/restud/rdae007)
|
|
2607
|
+
|
|
2608
|
+
This paper introduces the imputation estimator implemented in our `ImputationDiD` class:
|
|
2609
|
+
- **Efficient imputation**: OLS on untreated observations → impute counterfactuals → aggregate
|
|
2610
|
+
- **Conservative variance**: Theorem 3 clustered variance estimator with auxiliary model
|
|
2611
|
+
- **Pre-trend test**: Independent of treatment effect estimation (Proposition 9)
|
|
2612
|
+
- **Efficiency gains**: ~50% shorter CIs than Callaway-Sant'Anna under homogeneous effects
|
|
2613
|
+
|
|
2503
2614
|
- **Callaway, B., & Sant'Anna, P. H. C. (2021).** "Difference-in-Differences with Multiple Time Periods." *Journal of Econometrics*, 225(2), 200-230. [https://doi.org/10.1016/j.jeconom.2020.12.001](https://doi.org/10.1016/j.jeconom.2020.12.001)
|
|
2504
2615
|
|
|
2505
2616
|
- **Sant'Anna, P. H. C., & Zhao, J. (2020).** "Doubly Robust Difference-in-Differences Estimators." *Journal of Econometrics*, 219(1), 101-122. [https://doi.org/10.1016/j.jeconom.2020.06.003](https://doi.org/10.1016/j.jeconom.2020.06.003)
|
|
@@ -70,7 +70,7 @@ Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
|
|
|
70
70
|
- **Wild cluster bootstrap**: Valid inference with few clusters (<50) using Rademacher, Webb, or Mammen weights
|
|
71
71
|
- **Panel data support**: Two-way fixed effects estimator for panel designs
|
|
72
72
|
- **Multi-period analysis**: Event-study style DiD with period-specific treatment effects
|
|
73
|
-
- **Staggered adoption**: Callaway-Sant'Anna (2021)
|
|
73
|
+
- **Staggered adoption**: Callaway-Sant'Anna (2021), Sun-Abraham (2021), and Borusyak-Jaravel-Spiess (2024) imputation estimators for heterogeneous treatment timing
|
|
74
74
|
- **Triple Difference (DDD)**: Ortiz-Villavicencio & Sant'Anna (2025) estimators with proper covariate handling
|
|
75
75
|
- **Synthetic DiD**: Combined DiD with synthetic control for improved robustness
|
|
76
76
|
- **Triply Robust Panel (TROP)**: Factor-adjusted DiD with synthetic weights (Athey et al. 2025)
|
|
@@ -879,6 +879,54 @@ print(f"Sun-Abraham ATT: {sa_results.overall_att:.3f}")
|
|
|
879
879
|
# If results differ substantially, investigate heterogeneity
|
|
880
880
|
```
|
|
881
881
|
|
|
882
|
+
### Borusyak-Jaravel-Spiess Imputation Estimator
|
|
883
|
+
|
|
884
|
+
The Borusyak et al. (2024) imputation estimator is the **efficient** estimator for staggered DiD under parallel trends, producing ~50% shorter confidence intervals than Callaway-Sant'Anna and 2-3.5x shorter than Sun-Abraham under homogeneous treatment effects.
|
|
885
|
+
|
|
886
|
+
```python
|
|
887
|
+
from diff_diff import ImputationDiD, imputation_did
|
|
888
|
+
|
|
889
|
+
# Basic usage
|
|
890
|
+
est = ImputationDiD()
|
|
891
|
+
results = est.fit(data, outcome='outcome', unit='unit',
|
|
892
|
+
time='period', first_treat='first_treat')
|
|
893
|
+
results.print_summary()
|
|
894
|
+
|
|
895
|
+
# Event study
|
|
896
|
+
results = est.fit(data, outcome='outcome', unit='unit',
|
|
897
|
+
time='period', first_treat='first_treat',
|
|
898
|
+
aggregate='event_study')
|
|
899
|
+
|
|
900
|
+
# Pre-trend test (Equation 9)
|
|
901
|
+
pt = results.pretrend_test(n_leads=3)
|
|
902
|
+
print(f"F-stat: {pt['f_stat']:.3f}, p-value: {pt['p_value']:.4f}")
|
|
903
|
+
|
|
904
|
+
# Convenience function
|
|
905
|
+
results = imputation_did(data, 'outcome', 'unit', 'period', 'first_treat',
|
|
906
|
+
aggregate='all')
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
```python
|
|
910
|
+
ImputationDiD(
|
|
911
|
+
anticipation=0, # Number of anticipation periods
|
|
912
|
+
alpha=0.05, # Significance level
|
|
913
|
+
cluster=None, # Cluster variable (defaults to unit)
|
|
914
|
+
n_bootstrap=0, # Bootstrap iterations (0=analytical inference)
|
|
915
|
+
seed=None, # Random seed
|
|
916
|
+
horizon_max=None, # Max event-study horizon
|
|
917
|
+
aux_partition="cohort_horizon", # Variance partition: "cohort_horizon", "cohort", "horizon"
|
|
918
|
+
)
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
**When to use Imputation DiD vs Callaway-Sant'Anna:**
|
|
922
|
+
|
|
923
|
+
| Aspect | Imputation DiD | Callaway-Sant'Anna |
|
|
924
|
+
|--------|---------------|-------------------|
|
|
925
|
+
| Efficiency | Most efficient under homogeneous effects | Less efficient but more robust to heterogeneity |
|
|
926
|
+
| Control group | Always uses all untreated obs | Choice of never-treated or not-yet-treated |
|
|
927
|
+
| Inference | Conservative variance (Theorem 3) | Multiplier bootstrap |
|
|
928
|
+
| Pre-trends | Built-in F-test (Equation 9) | Separate testing |
|
|
929
|
+
|
|
882
930
|
### Triple Difference (DDD)
|
|
883
931
|
|
|
884
932
|
Triple Difference (DDD) is used when treatment requires satisfying two criteria: belonging to a treated **group** AND being in an eligible **partition**. The `TripleDifference` class implements the methodology from Ortiz-Villavicencio & Sant'Anna (2025), which correctly handles covariate adjustment (unlike naive implementations).
|
|
@@ -2000,6 +2048,60 @@ SunAbraham(
|
|
|
2000
2048
|
| `print_summary(alpha)` | Print summary to stdout |
|
|
2001
2049
|
| `to_dataframe(level)` | Convert to DataFrame ('event_study' or 'cohort') |
|
|
2002
2050
|
|
|
2051
|
+
### ImputationDiD
|
|
2052
|
+
|
|
2053
|
+
```python
|
|
2054
|
+
ImputationDiD(
|
|
2055
|
+
anticipation=0, # Periods of anticipation effects
|
|
2056
|
+
alpha=0.05, # Significance level for CIs
|
|
2057
|
+
cluster=None, # Column for cluster-robust SEs
|
|
2058
|
+
n_bootstrap=0, # Bootstrap iterations (0 = analytical)
|
|
2059
|
+
seed=None, # Random seed
|
|
2060
|
+
rank_deficient_action='warn', # 'warn', 'error', or 'silent'
|
|
2061
|
+
horizon_max=None, # Max event-study horizon
|
|
2062
|
+
aux_partition='cohort_horizon', # Variance partition
|
|
2063
|
+
)
|
|
2064
|
+
```
|
|
2065
|
+
|
|
2066
|
+
**fit() Parameters:**
|
|
2067
|
+
|
|
2068
|
+
| Parameter | Type | Description |
|
|
2069
|
+
|-----------|------|-------------|
|
|
2070
|
+
| `data` | DataFrame | Panel data |
|
|
2071
|
+
| `outcome` | str | Outcome variable column name |
|
|
2072
|
+
| `unit` | str | Unit identifier column |
|
|
2073
|
+
| `time` | str | Time period column |
|
|
2074
|
+
| `first_treat` | str | First treatment period column (0 for never-treated) |
|
|
2075
|
+
| `covariates` | list | Covariate column names |
|
|
2076
|
+
| `aggregate` | str | Aggregation: None, "event_study", "group", "all" |
|
|
2077
|
+
| `balance_e` | int | Balance event study to this many pre-treatment periods |
|
|
2078
|
+
|
|
2079
|
+
### ImputationDiDResults
|
|
2080
|
+
|
|
2081
|
+
**Attributes:**
|
|
2082
|
+
|
|
2083
|
+
| Attribute | Description |
|
|
2084
|
+
|-----------|-------------|
|
|
2085
|
+
| `overall_att` | Overall average treatment effect on the treated |
|
|
2086
|
+
| `overall_se` | Standard error (conservative, Theorem 3) |
|
|
2087
|
+
| `overall_t_stat` | T-statistic |
|
|
2088
|
+
| `overall_p_value` | P-value for H0: ATT = 0 |
|
|
2089
|
+
| `overall_conf_int` | Confidence interval |
|
|
2090
|
+
| `event_study_effects` | Dict of relative time -> effect dict (if `aggregate='event_study'` or `'all'`) |
|
|
2091
|
+
| `group_effects` | Dict of cohort -> effect dict (if `aggregate='group'` or `'all'`) |
|
|
2092
|
+
| `treatment_effects` | DataFrame of unit-level imputed treatment effects |
|
|
2093
|
+
| `n_treated_obs` | Number of treated observations |
|
|
2094
|
+
| `n_untreated_obs` | Number of untreated observations |
|
|
2095
|
+
|
|
2096
|
+
**Methods:**
|
|
2097
|
+
|
|
2098
|
+
| Method | Description |
|
|
2099
|
+
|--------|-------------|
|
|
2100
|
+
| `summary(alpha)` | Get formatted summary string |
|
|
2101
|
+
| `print_summary(alpha)` | Print summary to stdout |
|
|
2102
|
+
| `to_dataframe(level)` | Convert to DataFrame ('observation', 'event_study', 'group') |
|
|
2103
|
+
| `pretrend_test(n_leads)` | Run pre-trend F-test (Equation 9) |
|
|
2104
|
+
|
|
2003
2105
|
### TripleDifference
|
|
2004
2106
|
|
|
2005
2107
|
```python
|
|
@@ -2464,6 +2566,14 @@ The `HonestDiD` module implements sensitivity analysis methods for relaxing the
|
|
|
2464
2566
|
|
|
2465
2567
|
### Multi-Period and Staggered Adoption
|
|
2466
2568
|
|
|
2569
|
+
- **Borusyak, K., Jaravel, X., & Spiess, J. (2024).** "Revisiting Event-Study Designs: Robust and Efficient Estimation." *Review of Economic Studies*, 91(6), 3253-3285. [https://doi.org/10.1093/restud/rdae007](https://doi.org/10.1093/restud/rdae007)
|
|
2570
|
+
|
|
2571
|
+
This paper introduces the imputation estimator implemented in our `ImputationDiD` class:
|
|
2572
|
+
- **Efficient imputation**: OLS on untreated observations → impute counterfactuals → aggregate
|
|
2573
|
+
- **Conservative variance**: Theorem 3 clustered variance estimator with auxiliary model
|
|
2574
|
+
- **Pre-trend test**: Independent of treatment effect estimation (Proposition 9)
|
|
2575
|
+
- **Efficiency gains**: ~50% shorter CIs than Callaway-Sant'Anna under homogeneous effects
|
|
2576
|
+
|
|
2467
2577
|
- **Callaway, B., & Sant'Anna, P. H. C. (2021).** "Difference-in-Differences with Multiple Time Periods." *Journal of Econometrics*, 225(2), 200-230. [https://doi.org/10.1016/j.jeconom.2020.12.001](https://doi.org/10.1016/j.jeconom.2020.12.001)
|
|
2468
2578
|
|
|
2469
2579
|
- **Sant'Anna, P. H. C., & Zhao, J. (2020).** "Doubly Robust Difference-in-Differences Estimators." *Journal of Econometrics*, 219(1), 101-122. [https://doi.org/10.1016/j.jeconom.2020.06.003](https://doi.org/10.1016/j.jeconom.2020.06.003)
|
|
@@ -95,6 +95,12 @@ from diff_diff.staggered import (
|
|
|
95
95
|
CSBootstrapResults,
|
|
96
96
|
GroupTimeEffect,
|
|
97
97
|
)
|
|
98
|
+
from diff_diff.imputation import (
|
|
99
|
+
ImputationBootstrapResults,
|
|
100
|
+
ImputationDiD,
|
|
101
|
+
ImputationDiDResults,
|
|
102
|
+
imputation_did,
|
|
103
|
+
)
|
|
98
104
|
from diff_diff.sun_abraham import (
|
|
99
105
|
SABootstrapResults,
|
|
100
106
|
SunAbraham,
|
|
@@ -136,7 +142,7 @@ from diff_diff.datasets import (
|
|
|
136
142
|
load_mpdta,
|
|
137
143
|
)
|
|
138
144
|
|
|
139
|
-
__version__ = "2.
|
|
145
|
+
__version__ = "2.3.0"
|
|
140
146
|
__all__ = [
|
|
141
147
|
# Estimators
|
|
142
148
|
"DifferenceInDifferences",
|
|
@@ -145,6 +151,7 @@ __all__ = [
|
|
|
145
151
|
"SyntheticDiD",
|
|
146
152
|
"CallawaySantAnna",
|
|
147
153
|
"SunAbraham",
|
|
154
|
+
"ImputationDiD",
|
|
148
155
|
"TripleDifference",
|
|
149
156
|
"TROP",
|
|
150
157
|
# Bacon Decomposition
|
|
@@ -163,6 +170,9 @@ __all__ = [
|
|
|
163
170
|
"GroupTimeEffect",
|
|
164
171
|
"SunAbrahamResults",
|
|
165
172
|
"SABootstrapResults",
|
|
173
|
+
"ImputationDiDResults",
|
|
174
|
+
"ImputationBootstrapResults",
|
|
175
|
+
"imputation_did",
|
|
166
176
|
"TripleDifferenceResults",
|
|
167
177
|
"triple_difference",
|
|
168
178
|
"TROPResults",
|