diff-diff 0.6.0__tar.gz → 1.0.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.
Files changed (30) hide show
  1. {diff_diff-0.6.0/diff_diff.egg-info → diff_diff-1.0.0}/PKG-INFO +54 -6
  2. diff_diff-0.6.0/PKG-INFO → diff_diff-1.0.0/README.md +52 -39
  3. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/__init__.py +35 -1
  4. diff_diff-1.0.0/diff_diff/bacon.py +1027 -0
  5. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/estimators.py +138 -1
  6. diff_diff-1.0.0/diff_diff/power.py +1350 -0
  7. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/staggered.py +564 -13
  8. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/visualization.py +568 -0
  9. diff_diff-0.6.0/README.md → diff_diff-1.0.0/diff_diff.egg-info/PKG-INFO +87 -4
  10. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff.egg-info/SOURCES.txt +4 -0
  11. {diff_diff-0.6.0 → diff_diff-1.0.0}/pyproject.toml +2 -2
  12. diff_diff-1.0.0/tests/test_bacon.py +679 -0
  13. diff_diff-1.0.0/tests/test_power.py +691 -0
  14. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_staggered.py +369 -0
  15. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/diagnostics.py +0 -0
  16. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/honest_did.py +0 -0
  17. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/prep.py +0 -0
  18. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/results.py +0 -0
  19. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff/utils.py +0 -0
  20. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff.egg-info/dependency_links.txt +0 -0
  21. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff.egg-info/requires.txt +0 -0
  22. {diff_diff-0.6.0 → diff_diff-1.0.0}/diff_diff.egg-info/top_level.txt +0 -0
  23. {diff_diff-0.6.0 → diff_diff-1.0.0}/setup.cfg +0 -0
  24. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_diagnostics.py +0 -0
  25. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_estimators.py +0 -0
  26. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_honest_did.py +0 -0
  27. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_prep.py +0 -0
  28. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_utils.py +0 -0
  29. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_visualization.py +0 -0
  30. {diff_diff-0.6.0 → diff_diff-1.0.0}/tests/test_wild_bootstrap.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diff-diff
3
- Version: 0.6.0
3
+ Version: 1.0.0
4
4
  Summary: A library for Difference-in-Differences causal inference analysis
5
5
  Author: diff-diff contributors
6
6
  License-Expression: MIT
@@ -9,7 +9,7 @@ Project-URL: Documentation, https://diff-diff.readthedocs.io
9
9
  Project-URL: Repository, https://github.com/igerber/diff-diff
10
10
  Project-URL: Issues, https://github.com/igerber/diff-diff/issues
11
11
  Keywords: causal-inference,difference-in-differences,econometrics,statistics,treatment-effects
12
- Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Intended Audience :: Science/Research
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python :: 3
@@ -109,8 +109,10 @@ Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
109
109
  - **Synthetic DiD**: Combined DiD with synthetic control for improved robustness
110
110
  - **Event study plots**: Publication-ready visualization of treatment effects
111
111
  - **Parallel trends testing**: Multiple methods including equivalence tests
112
+ - **Goodman-Bacon decomposition**: Diagnose TWFE bias by decomposing into 2x2 comparisons
112
113
  - **Placebo tests**: Comprehensive diagnostics including fake timing, fake group, permutation, and leave-one-out tests
113
114
  - **Honest DiD sensitivity analysis**: Rambachan-Roth (2023) bounds and breakdown analysis for parallel trends violations
115
+ - **Power analysis**: MDE, sample size, and power calculations for study design; simulation-based power for any estimator
114
116
  - **Data prep utilities**: Helper functions for common data preparation tasks
115
117
 
116
118
  ## Tutorials
@@ -120,10 +122,11 @@ We provide Jupyter notebook tutorials in `docs/tutorials/`:
120
122
  | Notebook | Description |
121
123
  |----------|-------------|
122
124
  | `01_basic_did.ipynb` | Basic 2x2 DiD, formula interface, covariates, fixed effects, cluster-robust SE, wild bootstrap |
123
- | `02_staggered_did.ipynb` | Staggered adoption with Callaway-Sant'Anna, group-time effects, aggregation methods |
125
+ | `02_staggered_did.ipynb` | Staggered adoption with Callaway-Sant'Anna, group-time effects, aggregation methods, Bacon decomposition |
124
126
  | `03_synthetic_did.ipynb` | Synthetic DiD, unit/time weights, inference methods, regularization |
125
127
  | `04_parallel_trends.ipynb` | Testing parallel trends, equivalence tests, placebo tests, diagnostics |
126
128
  | `05_honest_did.ipynb` | Honest DiD sensitivity analysis, bounds, breakdown values, visualization |
129
+ | `06_power_analysis.ipynb` | Power analysis, MDE, sample size calculations, simulation-based power |
127
130
 
128
131
  ## Data Preparation
129
132
 
@@ -734,10 +737,48 @@ CallawaySantAnna(
734
737
  alpha=0.05, # Significance level
735
738
  cluster=None, # Column for cluster SEs
736
739
  n_bootstrap=0, # Bootstrap iterations (0 = analytical SEs)
740
+ bootstrap_weight_type='rademacher', # 'rademacher', 'mammen', or 'webb'
737
741
  seed=None # Random seed
738
742
  )
739
743
  ```
740
744
 
745
+ **Multiplier bootstrap for inference:**
746
+
747
+ With few clusters or when analytical standard errors may be unreliable, use the multiplier bootstrap for valid inference. This implements the approach from Callaway & Sant'Anna (2021).
748
+
749
+ ```python
750
+ # Bootstrap inference with 999 iterations
751
+ cs = CallawaySantAnna(
752
+ n_bootstrap=999,
753
+ bootstrap_weight_type='rademacher', # or 'mammen', 'webb'
754
+ seed=42
755
+ )
756
+ results = cs.fit(
757
+ data,
758
+ outcome='sales',
759
+ unit='firm_id',
760
+ time='year',
761
+ first_treat='first_treat',
762
+ aggregate='event_study'
763
+ )
764
+
765
+ # Access bootstrap results
766
+ print(f"Overall ATT: {results.overall_att:.3f}")
767
+ print(f"Bootstrap SE: {results.bootstrap_results.overall_att_se:.3f}")
768
+ print(f"Bootstrap 95% CI: {results.bootstrap_results.overall_att_ci}")
769
+ print(f"Bootstrap p-value: {results.bootstrap_results.overall_att_p_value:.4f}")
770
+
771
+ # Event study bootstrap inference
772
+ for rel_time, se in results.bootstrap_results.event_study_ses.items():
773
+ ci = results.bootstrap_results.event_study_cis[rel_time]
774
+ print(f"e={rel_time}: SE={se:.3f}, 95% CI=[{ci[0]:.3f}, {ci[1]:.3f}]")
775
+ ```
776
+
777
+ **Bootstrap weight types:**
778
+ - `'rademacher'` - Default, ±1 with p=0.5, good for most cases
779
+ - `'mammen'` - Two-point distribution matching first 3 moments
780
+ - `'webb'` - Six-point distribution, recommended for very few clusters (<10)
781
+
741
782
  **Covariate adjustment for conditional parallel trends:**
742
783
 
743
784
  When parallel trends only holds conditional on covariates, use the `covariates` parameter:
@@ -756,9 +797,6 @@ results = cs.fit(
756
797
  )
757
798
  ```
758
799
 
759
- **Current limitations:**
760
- - Bootstrap inference (`n_bootstrap > 0`) is not yet fully implemented
761
-
762
800
  ### Event Study Visualization
763
801
 
764
802
  Create publication-ready event study plots:
@@ -1729,6 +1767,16 @@ The `HonestDiD` module implements sensitivity analysis methods for relaxing the
1729
1767
 
1730
1768
  - **Goodman-Bacon, A. (2021).** "Difference-in-Differences with Variation in Treatment Timing." *Journal of Econometrics*, 225(2), 254-277. [https://doi.org/10.1016/j.jeconom.2021.03.014](https://doi.org/10.1016/j.jeconom.2021.03.014)
1731
1769
 
1770
+ ### Power Analysis
1771
+
1772
+ - **Bloom, H. S. (1995).** "Minimum Detectable Effects: A Simple Way to Report the Statistical Power of Experimental Designs." *Evaluation Review*, 19(5), 547-556. [https://doi.org/10.1177/0193841X9501900504](https://doi.org/10.1177/0193841X9501900504)
1773
+
1774
+ - **Burlig, F., Preonas, L., & Woerman, M. (2020).** "Panel Data and Experimental Design." *Journal of Development Economics*, 144, 102458. [https://doi.org/10.1016/j.jdeveco.2020.102458](https://doi.org/10.1016/j.jdeveco.2020.102458)
1775
+
1776
+ Essential reference for power analysis in panel DiD designs. Discusses how serial correlation (ICC) affects power and provides formulas for panel data settings.
1777
+
1778
+ - **Djimeu, E. W., & Houndolo, D.-G. (2016).** "Power Calculation for Causal Inference in Social Science: Sample Size and Minimum Detectable Effect Determination." *Journal of Development Effectiveness*, 8(4), 508-527. [https://doi.org/10.1080/19439342.2016.1244555](https://doi.org/10.1080/19439342.2016.1244555)
1779
+
1732
1780
  ### General Causal Inference
1733
1781
 
1734
1782
  - **Imbens, G. W., & Rubin, D. B. (2015).** *Causal Inference for Statistics, Social, and Biomedical Sciences: An Introduction*. Cambridge University Press.
@@ -1,38 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: diff-diff
3
- Version: 0.6.0
4
- Summary: A library for Difference-in-Differences causal inference analysis
5
- Author: diff-diff contributors
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/igerber/diff-diff
8
- Project-URL: Documentation, https://diff-diff.readthedocs.io
9
- Project-URL: Repository, https://github.com/igerber/diff-diff
10
- Project-URL: Issues, https://github.com/igerber/diff-diff/issues
11
- Keywords: causal-inference,difference-in-differences,econometrics,statistics,treatment-effects
12
- Classifier: Development Status :: 3 - Alpha
13
- Classifier: Intended Audience :: Science/Research
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Topic :: Scientific/Engineering :: Mathematics
21
- Requires-Python: >=3.9
22
- Description-Content-Type: text/markdown
23
- Requires-Dist: numpy>=1.20.0
24
- Requires-Dist: pandas>=1.3.0
25
- Requires-Dist: scipy>=1.7.0
26
- Provides-Extra: dev
27
- Requires-Dist: pytest>=7.0; extra == "dev"
28
- Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
- Requires-Dist: black>=23.0; extra == "dev"
30
- Requires-Dist: ruff>=0.1.0; extra == "dev"
31
- Requires-Dist: mypy>=1.0; extra == "dev"
32
- Provides-Extra: docs
33
- Requires-Dist: sphinx>=6.0; extra == "docs"
34
- Requires-Dist: sphinx-rtd-theme>=1.0; extra == "docs"
35
-
36
1
  # diff-diff
37
2
 
38
3
  A Python library for Difference-in-Differences (DiD) causal inference analysis with an sklearn-like API and statsmodels-style outputs.
@@ -109,8 +74,10 @@ Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
109
74
  - **Synthetic DiD**: Combined DiD with synthetic control for improved robustness
110
75
  - **Event study plots**: Publication-ready visualization of treatment effects
111
76
  - **Parallel trends testing**: Multiple methods including equivalence tests
77
+ - **Goodman-Bacon decomposition**: Diagnose TWFE bias by decomposing into 2x2 comparisons
112
78
  - **Placebo tests**: Comprehensive diagnostics including fake timing, fake group, permutation, and leave-one-out tests
113
79
  - **Honest DiD sensitivity analysis**: Rambachan-Roth (2023) bounds and breakdown analysis for parallel trends violations
80
+ - **Power analysis**: MDE, sample size, and power calculations for study design; simulation-based power for any estimator
114
81
  - **Data prep utilities**: Helper functions for common data preparation tasks
115
82
 
116
83
  ## Tutorials
@@ -120,10 +87,11 @@ We provide Jupyter notebook tutorials in `docs/tutorials/`:
120
87
  | Notebook | Description |
121
88
  |----------|-------------|
122
89
  | `01_basic_did.ipynb` | Basic 2x2 DiD, formula interface, covariates, fixed effects, cluster-robust SE, wild bootstrap |
123
- | `02_staggered_did.ipynb` | Staggered adoption with Callaway-Sant'Anna, group-time effects, aggregation methods |
90
+ | `02_staggered_did.ipynb` | Staggered adoption with Callaway-Sant'Anna, group-time effects, aggregation methods, Bacon decomposition |
124
91
  | `03_synthetic_did.ipynb` | Synthetic DiD, unit/time weights, inference methods, regularization |
125
92
  | `04_parallel_trends.ipynb` | Testing parallel trends, equivalence tests, placebo tests, diagnostics |
126
93
  | `05_honest_did.ipynb` | Honest DiD sensitivity analysis, bounds, breakdown values, visualization |
94
+ | `06_power_analysis.ipynb` | Power analysis, MDE, sample size calculations, simulation-based power |
127
95
 
128
96
  ## Data Preparation
129
97
 
@@ -734,10 +702,48 @@ CallawaySantAnna(
734
702
  alpha=0.05, # Significance level
735
703
  cluster=None, # Column for cluster SEs
736
704
  n_bootstrap=0, # Bootstrap iterations (0 = analytical SEs)
705
+ bootstrap_weight_type='rademacher', # 'rademacher', 'mammen', or 'webb'
737
706
  seed=None # Random seed
738
707
  )
739
708
  ```
740
709
 
710
+ **Multiplier bootstrap for inference:**
711
+
712
+ With few clusters or when analytical standard errors may be unreliable, use the multiplier bootstrap for valid inference. This implements the approach from Callaway & Sant'Anna (2021).
713
+
714
+ ```python
715
+ # Bootstrap inference with 999 iterations
716
+ cs = CallawaySantAnna(
717
+ n_bootstrap=999,
718
+ bootstrap_weight_type='rademacher', # or 'mammen', 'webb'
719
+ seed=42
720
+ )
721
+ results = cs.fit(
722
+ data,
723
+ outcome='sales',
724
+ unit='firm_id',
725
+ time='year',
726
+ first_treat='first_treat',
727
+ aggregate='event_study'
728
+ )
729
+
730
+ # Access bootstrap results
731
+ print(f"Overall ATT: {results.overall_att:.3f}")
732
+ print(f"Bootstrap SE: {results.bootstrap_results.overall_att_se:.3f}")
733
+ print(f"Bootstrap 95% CI: {results.bootstrap_results.overall_att_ci}")
734
+ print(f"Bootstrap p-value: {results.bootstrap_results.overall_att_p_value:.4f}")
735
+
736
+ # Event study bootstrap inference
737
+ for rel_time, se in results.bootstrap_results.event_study_ses.items():
738
+ ci = results.bootstrap_results.event_study_cis[rel_time]
739
+ print(f"e={rel_time}: SE={se:.3f}, 95% CI=[{ci[0]:.3f}, {ci[1]:.3f}]")
740
+ ```
741
+
742
+ **Bootstrap weight types:**
743
+ - `'rademacher'` - Default, ±1 with p=0.5, good for most cases
744
+ - `'mammen'` - Two-point distribution matching first 3 moments
745
+ - `'webb'` - Six-point distribution, recommended for very few clusters (<10)
746
+
741
747
  **Covariate adjustment for conditional parallel trends:**
742
748
 
743
749
  When parallel trends only holds conditional on covariates, use the `covariates` parameter:
@@ -756,9 +762,6 @@ results = cs.fit(
756
762
  )
757
763
  ```
758
764
 
759
- **Current limitations:**
760
- - Bootstrap inference (`n_bootstrap > 0`) is not yet fully implemented
761
-
762
765
  ### Event Study Visualization
763
766
 
764
767
  Create publication-ready event study plots:
@@ -1729,6 +1732,16 @@ The `HonestDiD` module implements sensitivity analysis methods for relaxing the
1729
1732
 
1730
1733
  - **Goodman-Bacon, A. (2021).** "Difference-in-Differences with Variation in Treatment Timing." *Journal of Econometrics*, 225(2), 254-277. [https://doi.org/10.1016/j.jeconom.2021.03.014](https://doi.org/10.1016/j.jeconom.2021.03.014)
1731
1734
 
1735
+ ### Power Analysis
1736
+
1737
+ - **Bloom, H. S. (1995).** "Minimum Detectable Effects: A Simple Way to Report the Statistical Power of Experimental Designs." *Evaluation Review*, 19(5), 547-556. [https://doi.org/10.1177/0193841X9501900504](https://doi.org/10.1177/0193841X9501900504)
1738
+
1739
+ - **Burlig, F., Preonas, L., & Woerman, M. (2020).** "Panel Data and Experimental Design." *Journal of Development Economics*, 144, 102458. [https://doi.org/10.1016/j.jdeveco.2020.102458](https://doi.org/10.1016/j.jdeveco.2020.102458)
1740
+
1741
+ Essential reference for power analysis in panel DiD designs. Discusses how serial correlation (ICC) affects power and provides formulas for panel data settings.
1742
+
1743
+ - **Djimeu, E. W., & Houndolo, D.-G. (2016).** "Power Calculation for Causal Inference in Social Science: Sample Size and Minimum Detectable Effect Determination." *Journal of Development Effectiveness*, 8(4), 508-527. [https://doi.org/10.1080/19439342.2016.1244555](https://doi.org/10.1080/19439342.2016.1244555)
1744
+
1732
1745
  ### General Causal Inference
1733
1746
 
1734
1747
  - **Imbens, G. W., & Rubin, D. B. (2015).** *Causal Inference for Statistics, Social, and Biomedical Sciences: An Introduction*. Cambridge University Press.
@@ -5,6 +5,12 @@ This library provides sklearn-like estimators for causal inference
5
5
  using the difference-in-differences methodology.
6
6
  """
7
7
 
8
+ from diff_diff.bacon import (
9
+ BaconDecomposition,
10
+ BaconDecompositionResults,
11
+ Comparison2x2,
12
+ bacon_decompose,
13
+ )
8
14
  from diff_diff.diagnostics import (
9
15
  PlaceboTestResults,
10
16
  leave_one_out_test,
@@ -30,6 +36,15 @@ from diff_diff.honest_did import (
30
36
  compute_honest_did,
31
37
  sensitivity_plot,
32
38
  )
39
+ from diff_diff.power import (
40
+ PowerAnalysis,
41
+ PowerResults,
42
+ SimulationPowerResults,
43
+ compute_mde,
44
+ compute_power,
45
+ compute_sample_size,
46
+ simulate_power,
47
+ )
33
48
  from diff_diff.prep import (
34
49
  aggregate_to_cohorts,
35
50
  balance_panel,
@@ -51,6 +66,7 @@ from diff_diff.results import (
51
66
  from diff_diff.staggered import (
52
67
  CallawaySantAnna,
53
68
  CallawaySantAnnaResults,
69
+ CSBootstrapResults,
54
70
  GroupTimeEffect,
55
71
  )
56
72
  from diff_diff.utils import (
@@ -61,13 +77,15 @@ from diff_diff.utils import (
61
77
  wild_bootstrap_se,
62
78
  )
63
79
  from diff_diff.visualization import (
80
+ plot_bacon,
64
81
  plot_event_study,
65
82
  plot_group_effects,
66
83
  plot_honest_event_study,
84
+ plot_power_curve,
67
85
  plot_sensitivity,
68
86
  )
69
87
 
70
- __version__ = "0.6.0"
88
+ __version__ = "1.0.0"
71
89
  __all__ = [
72
90
  # Estimators
73
91
  "DifferenceInDifferences",
@@ -75,12 +93,19 @@ __all__ = [
75
93
  "MultiPeriodDiD",
76
94
  "SyntheticDiD",
77
95
  "CallawaySantAnna",
96
+ # Bacon Decomposition
97
+ "BaconDecomposition",
98
+ "BaconDecompositionResults",
99
+ "Comparison2x2",
100
+ "bacon_decompose",
101
+ "plot_bacon",
78
102
  # Results
79
103
  "DiDResults",
80
104
  "MultiPeriodDiDResults",
81
105
  "SyntheticDiDResults",
82
106
  "PeriodEffect",
83
107
  "CallawaySantAnnaResults",
108
+ "CSBootstrapResults",
84
109
  "GroupTimeEffect",
85
110
  # Visualization
86
111
  "plot_event_study",
@@ -122,4 +147,13 @@ __all__ = [
122
147
  "DeltaSDRM",
123
148
  "compute_honest_did",
124
149
  "sensitivity_plot",
150
+ # Power analysis
151
+ "PowerAnalysis",
152
+ "PowerResults",
153
+ "SimulationPowerResults",
154
+ "compute_mde",
155
+ "compute_power",
156
+ "compute_sample_size",
157
+ "simulate_power",
158
+ "plot_power_curve",
125
159
  ]