diff-diff 0.1.0__tar.gz → 0.2.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-0.1.0 → diff_diff-0.2.0}/PKG-INFO +128 -2
- {diff_diff-0.1.0 → diff_diff-0.2.0}/README.md +126 -0
- diff_diff-0.2.0/diff_diff/__init__.py +18 -0
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff/estimators.py +356 -7
- diff_diff-0.2.0/diff_diff/results.py +463 -0
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff/utils.py +74 -20
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff.egg-info/PKG-INFO +128 -2
- {diff_diff-0.1.0 → diff_diff-0.2.0}/pyproject.toml +2 -2
- diff_diff-0.2.0/tests/test_estimators.py +1563 -0
- diff_diff-0.1.0/diff_diff/__init__.py +0 -12
- diff_diff-0.1.0/diff_diff/results.py +0 -170
- diff_diff-0.1.0/tests/test_estimators.py +0 -690
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff.egg-info/SOURCES.txt +0 -0
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff.egg-info/dependency_links.txt +0 -0
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff.egg-info/requires.txt +0 -0
- {diff_diff-0.1.0 → diff_diff-0.2.0}/diff_diff.egg-info/top_level.txt +0 -0
- {diff_diff-0.1.0 → diff_diff-0.2.0}/setup.cfg +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diff-diff
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A library for Difference-in-Differences causal inference analysis
|
|
5
5
|
Author: diff-diff contributors
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/igerber/diff-diff
|
|
8
8
|
Project-URL: Documentation, https://github.com/igerber/diff-diff#readme
|
|
9
9
|
Project-URL: Repository, https://github.com/igerber/diff-diff
|
|
@@ -103,6 +103,7 @@ Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
|
|
|
103
103
|
- **Multiple interfaces**: Column names or R-style formulas
|
|
104
104
|
- **Robust inference**: Heteroskedasticity-robust (HC1) and cluster-robust standard errors
|
|
105
105
|
- **Panel data support**: Two-way fixed effects estimator for panel designs
|
|
106
|
+
- **Multi-period analysis**: Event-study style DiD with period-specific treatment effects
|
|
106
107
|
|
|
107
108
|
## Usage
|
|
108
109
|
|
|
@@ -224,6 +225,66 @@ results = twfe.fit(
|
|
|
224
225
|
)
|
|
225
226
|
```
|
|
226
227
|
|
|
228
|
+
### Multi-Period DiD (Event Study)
|
|
229
|
+
|
|
230
|
+
For settings with multiple pre- and post-treatment periods:
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from diff_diff import MultiPeriodDiD
|
|
234
|
+
|
|
235
|
+
# Fit with multiple time periods
|
|
236
|
+
did = MultiPeriodDiD()
|
|
237
|
+
results = did.fit(
|
|
238
|
+
panel_data,
|
|
239
|
+
outcome='sales',
|
|
240
|
+
treatment='treated',
|
|
241
|
+
time='period',
|
|
242
|
+
post_periods=[3, 4, 5], # Periods 3-5 are post-treatment
|
|
243
|
+
reference_period=0 # Reference period for comparison
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# View period-specific treatment effects
|
|
247
|
+
for period, effect in results.period_effects.items():
|
|
248
|
+
print(f"Period {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
|
|
249
|
+
|
|
250
|
+
# View average treatment effect across post-periods
|
|
251
|
+
print(f"Average ATT: {results.avg_att:.3f}")
|
|
252
|
+
print(f"Average SE: {results.avg_se:.3f}")
|
|
253
|
+
|
|
254
|
+
# Full summary with all period effects
|
|
255
|
+
results.print_summary()
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Output:
|
|
259
|
+
```
|
|
260
|
+
================================================================================
|
|
261
|
+
Multi-Period Difference-in-Differences Estimation Results
|
|
262
|
+
================================================================================
|
|
263
|
+
|
|
264
|
+
Observations: 600
|
|
265
|
+
Pre-treatment periods: 3
|
|
266
|
+
Post-treatment periods: 3
|
|
267
|
+
|
|
268
|
+
--------------------------------------------------------------------------------
|
|
269
|
+
Average Treatment Effect
|
|
270
|
+
--------------------------------------------------------------------------------
|
|
271
|
+
Average ATT 5.2000 0.8234 6.315 0.0000
|
|
272
|
+
--------------------------------------------------------------------------------
|
|
273
|
+
95% Confidence Interval: [3.5862, 6.8138]
|
|
274
|
+
|
|
275
|
+
Period-Specific Effects:
|
|
276
|
+
--------------------------------------------------------------------------------
|
|
277
|
+
Period Effect Std. Err. t-stat P>|t|
|
|
278
|
+
--------------------------------------------------------------------------------
|
|
279
|
+
3 4.5000 0.9512 4.731 0.0000***
|
|
280
|
+
4 5.2000 0.8876 5.858 0.0000***
|
|
281
|
+
5 5.9000 0.9123 6.468 0.0000***
|
|
282
|
+
--------------------------------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
|
|
285
|
+
================================================================================
|
|
286
|
+
```
|
|
287
|
+
|
|
227
288
|
## Working with Results
|
|
228
289
|
|
|
229
290
|
### Export Results
|
|
@@ -395,6 +456,71 @@ DifferenceInDifferences(
|
|
|
395
456
|
| `to_dict()` | Convert to dictionary |
|
|
396
457
|
| `to_dataframe()` | Convert to pandas DataFrame |
|
|
397
458
|
|
|
459
|
+
### MultiPeriodDiD
|
|
460
|
+
|
|
461
|
+
```python
|
|
462
|
+
MultiPeriodDiD(
|
|
463
|
+
robust=True, # Use HC1 robust standard errors
|
|
464
|
+
cluster=None, # Column for cluster-robust SEs
|
|
465
|
+
alpha=0.05 # Significance level for CIs
|
|
466
|
+
)
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**fit() Parameters:**
|
|
470
|
+
|
|
471
|
+
| Parameter | Type | Description |
|
|
472
|
+
|-----------|------|-------------|
|
|
473
|
+
| `data` | DataFrame | Input data |
|
|
474
|
+
| `outcome` | str | Outcome variable column name |
|
|
475
|
+
| `treatment` | str | Treatment indicator column (0/1) |
|
|
476
|
+
| `time` | str | Time period column (multiple values) |
|
|
477
|
+
| `post_periods` | list | List of post-treatment period values |
|
|
478
|
+
| `covariates` | list | Linear control variables |
|
|
479
|
+
| `fixed_effects` | list | Categorical FE columns (creates dummies) |
|
|
480
|
+
| `absorb` | list | High-dimensional FE (within-transformation) |
|
|
481
|
+
| `reference_period` | any | Omitted period for time dummies |
|
|
482
|
+
|
|
483
|
+
### MultiPeriodDiDResults
|
|
484
|
+
|
|
485
|
+
**Attributes:**
|
|
486
|
+
|
|
487
|
+
| Attribute | Description |
|
|
488
|
+
|-----------|-------------|
|
|
489
|
+
| `period_effects` | Dict mapping periods to PeriodEffect objects |
|
|
490
|
+
| `avg_att` | Average ATT across post-treatment periods |
|
|
491
|
+
| `avg_se` | Standard error of average ATT |
|
|
492
|
+
| `avg_t_stat` | T-statistic for average ATT |
|
|
493
|
+
| `avg_p_value` | P-value for average ATT |
|
|
494
|
+
| `avg_conf_int` | Confidence interval for average ATT |
|
|
495
|
+
| `n_obs` | Number of observations |
|
|
496
|
+
| `pre_periods` | List of pre-treatment periods |
|
|
497
|
+
| `post_periods` | List of post-treatment periods |
|
|
498
|
+
|
|
499
|
+
**Methods:**
|
|
500
|
+
|
|
501
|
+
| Method | Description |
|
|
502
|
+
|--------|-------------|
|
|
503
|
+
| `get_effect(period)` | Get PeriodEffect for specific period |
|
|
504
|
+
| `summary(alpha)` | Get formatted summary string |
|
|
505
|
+
| `print_summary(alpha)` | Print summary to stdout |
|
|
506
|
+
| `to_dict()` | Convert to dictionary |
|
|
507
|
+
| `to_dataframe()` | Convert to pandas DataFrame |
|
|
508
|
+
|
|
509
|
+
### PeriodEffect
|
|
510
|
+
|
|
511
|
+
**Attributes:**
|
|
512
|
+
|
|
513
|
+
| Attribute | Description |
|
|
514
|
+
|-----------|-------------|
|
|
515
|
+
| `period` | Time period identifier |
|
|
516
|
+
| `effect` | Treatment effect estimate |
|
|
517
|
+
| `se` | Standard error |
|
|
518
|
+
| `t_stat` | T-statistic |
|
|
519
|
+
| `p_value` | P-value |
|
|
520
|
+
| `conf_int` | Confidence interval |
|
|
521
|
+
| `is_significant` | Boolean for significance at 0.05 |
|
|
522
|
+
| `significance_stars` | String of significance stars |
|
|
523
|
+
|
|
398
524
|
## Requirements
|
|
399
525
|
|
|
400
526
|
- Python >= 3.9
|
|
@@ -68,6 +68,7 @@ Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
|
|
|
68
68
|
- **Multiple interfaces**: Column names or R-style formulas
|
|
69
69
|
- **Robust inference**: Heteroskedasticity-robust (HC1) and cluster-robust standard errors
|
|
70
70
|
- **Panel data support**: Two-way fixed effects estimator for panel designs
|
|
71
|
+
- **Multi-period analysis**: Event-study style DiD with period-specific treatment effects
|
|
71
72
|
|
|
72
73
|
## Usage
|
|
73
74
|
|
|
@@ -189,6 +190,66 @@ results = twfe.fit(
|
|
|
189
190
|
)
|
|
190
191
|
```
|
|
191
192
|
|
|
193
|
+
### Multi-Period DiD (Event Study)
|
|
194
|
+
|
|
195
|
+
For settings with multiple pre- and post-treatment periods:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from diff_diff import MultiPeriodDiD
|
|
199
|
+
|
|
200
|
+
# Fit with multiple time periods
|
|
201
|
+
did = MultiPeriodDiD()
|
|
202
|
+
results = did.fit(
|
|
203
|
+
panel_data,
|
|
204
|
+
outcome='sales',
|
|
205
|
+
treatment='treated',
|
|
206
|
+
time='period',
|
|
207
|
+
post_periods=[3, 4, 5], # Periods 3-5 are post-treatment
|
|
208
|
+
reference_period=0 # Reference period for comparison
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# View period-specific treatment effects
|
|
212
|
+
for period, effect in results.period_effects.items():
|
|
213
|
+
print(f"Period {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
|
|
214
|
+
|
|
215
|
+
# View average treatment effect across post-periods
|
|
216
|
+
print(f"Average ATT: {results.avg_att:.3f}")
|
|
217
|
+
print(f"Average SE: {results.avg_se:.3f}")
|
|
218
|
+
|
|
219
|
+
# Full summary with all period effects
|
|
220
|
+
results.print_summary()
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Output:
|
|
224
|
+
```
|
|
225
|
+
================================================================================
|
|
226
|
+
Multi-Period Difference-in-Differences Estimation Results
|
|
227
|
+
================================================================================
|
|
228
|
+
|
|
229
|
+
Observations: 600
|
|
230
|
+
Pre-treatment periods: 3
|
|
231
|
+
Post-treatment periods: 3
|
|
232
|
+
|
|
233
|
+
--------------------------------------------------------------------------------
|
|
234
|
+
Average Treatment Effect
|
|
235
|
+
--------------------------------------------------------------------------------
|
|
236
|
+
Average ATT 5.2000 0.8234 6.315 0.0000
|
|
237
|
+
--------------------------------------------------------------------------------
|
|
238
|
+
95% Confidence Interval: [3.5862, 6.8138]
|
|
239
|
+
|
|
240
|
+
Period-Specific Effects:
|
|
241
|
+
--------------------------------------------------------------------------------
|
|
242
|
+
Period Effect Std. Err. t-stat P>|t|
|
|
243
|
+
--------------------------------------------------------------------------------
|
|
244
|
+
3 4.5000 0.9512 4.731 0.0000***
|
|
245
|
+
4 5.2000 0.8876 5.858 0.0000***
|
|
246
|
+
5 5.9000 0.9123 6.468 0.0000***
|
|
247
|
+
--------------------------------------------------------------------------------
|
|
248
|
+
|
|
249
|
+
Signif. codes: '***' 0.001, '**' 0.01, '*' 0.05, '.' 0.1
|
|
250
|
+
================================================================================
|
|
251
|
+
```
|
|
252
|
+
|
|
192
253
|
## Working with Results
|
|
193
254
|
|
|
194
255
|
### Export Results
|
|
@@ -360,6 +421,71 @@ DifferenceInDifferences(
|
|
|
360
421
|
| `to_dict()` | Convert to dictionary |
|
|
361
422
|
| `to_dataframe()` | Convert to pandas DataFrame |
|
|
362
423
|
|
|
424
|
+
### MultiPeriodDiD
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
MultiPeriodDiD(
|
|
428
|
+
robust=True, # Use HC1 robust standard errors
|
|
429
|
+
cluster=None, # Column for cluster-robust SEs
|
|
430
|
+
alpha=0.05 # Significance level for CIs
|
|
431
|
+
)
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**fit() Parameters:**
|
|
435
|
+
|
|
436
|
+
| Parameter | Type | Description |
|
|
437
|
+
|-----------|------|-------------|
|
|
438
|
+
| `data` | DataFrame | Input data |
|
|
439
|
+
| `outcome` | str | Outcome variable column name |
|
|
440
|
+
| `treatment` | str | Treatment indicator column (0/1) |
|
|
441
|
+
| `time` | str | Time period column (multiple values) |
|
|
442
|
+
| `post_periods` | list | List of post-treatment period values |
|
|
443
|
+
| `covariates` | list | Linear control variables |
|
|
444
|
+
| `fixed_effects` | list | Categorical FE columns (creates dummies) |
|
|
445
|
+
| `absorb` | list | High-dimensional FE (within-transformation) |
|
|
446
|
+
| `reference_period` | any | Omitted period for time dummies |
|
|
447
|
+
|
|
448
|
+
### MultiPeriodDiDResults
|
|
449
|
+
|
|
450
|
+
**Attributes:**
|
|
451
|
+
|
|
452
|
+
| Attribute | Description |
|
|
453
|
+
|-----------|-------------|
|
|
454
|
+
| `period_effects` | Dict mapping periods to PeriodEffect objects |
|
|
455
|
+
| `avg_att` | Average ATT across post-treatment periods |
|
|
456
|
+
| `avg_se` | Standard error of average ATT |
|
|
457
|
+
| `avg_t_stat` | T-statistic for average ATT |
|
|
458
|
+
| `avg_p_value` | P-value for average ATT |
|
|
459
|
+
| `avg_conf_int` | Confidence interval for average ATT |
|
|
460
|
+
| `n_obs` | Number of observations |
|
|
461
|
+
| `pre_periods` | List of pre-treatment periods |
|
|
462
|
+
| `post_periods` | List of post-treatment periods |
|
|
463
|
+
|
|
464
|
+
**Methods:**
|
|
465
|
+
|
|
466
|
+
| Method | Description |
|
|
467
|
+
|--------|-------------|
|
|
468
|
+
| `get_effect(period)` | Get PeriodEffect for specific period |
|
|
469
|
+
| `summary(alpha)` | Get formatted summary string |
|
|
470
|
+
| `print_summary(alpha)` | Print summary to stdout |
|
|
471
|
+
| `to_dict()` | Convert to dictionary |
|
|
472
|
+
| `to_dataframe()` | Convert to pandas DataFrame |
|
|
473
|
+
|
|
474
|
+
### PeriodEffect
|
|
475
|
+
|
|
476
|
+
**Attributes:**
|
|
477
|
+
|
|
478
|
+
| Attribute | Description |
|
|
479
|
+
|-----------|-------------|
|
|
480
|
+
| `period` | Time period identifier |
|
|
481
|
+
| `effect` | Treatment effect estimate |
|
|
482
|
+
| `se` | Standard error |
|
|
483
|
+
| `t_stat` | T-statistic |
|
|
484
|
+
| `p_value` | P-value |
|
|
485
|
+
| `conf_int` | Confidence interval |
|
|
486
|
+
| `is_significant` | Boolean for significance at 0.05 |
|
|
487
|
+
| `significance_stars` | String of significance stars |
|
|
488
|
+
|
|
363
489
|
## Requirements
|
|
364
490
|
|
|
365
491
|
- Python >= 3.9
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
diff-diff: A library for Difference-in-Differences analysis.
|
|
3
|
+
|
|
4
|
+
This library provides sklearn-like estimators for causal inference
|
|
5
|
+
using the difference-in-differences methodology.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from diff_diff.estimators import DifferenceInDifferences, MultiPeriodDiD
|
|
9
|
+
from diff_diff.results import DiDResults, MultiPeriodDiDResults, PeriodEffect
|
|
10
|
+
|
|
11
|
+
__version__ = "0.2.0"
|
|
12
|
+
__all__ = [
|
|
13
|
+
"DifferenceInDifferences",
|
|
14
|
+
"MultiPeriodDiD",
|
|
15
|
+
"DiDResults",
|
|
16
|
+
"MultiPeriodDiDResults",
|
|
17
|
+
"PeriodEffect",
|
|
18
|
+
]
|