diff-diff 2.2.0__tar.gz → 2.2.1__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.0 → diff_diff-2.2.1}/PKG-INFO +33 -22
- {diff_diff-2.2.0 → diff_diff-2.2.1}/README.md +31 -21
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/__init__.py +1 -1
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/diagnostics.py +3 -3
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/estimators.py +156 -42
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/honest_did.py +158 -147
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/pretrends.py +89 -151
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/results.py +164 -88
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/sun_abraham.py +6 -6
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/triple_diff.py +2 -2
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/trop.py +80 -325
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/visualization.py +206 -213
- {diff_diff-2.2.0 → diff_diff-2.2.1}/pyproject.toml +2 -1
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/Cargo.lock +29 -29
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/Cargo.toml +1 -1
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/src/trop.rs +149 -136
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/_backend.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/bacon.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/datasets.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/linalg.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/power.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/prep.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/prep_dgp.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/staggered.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/staggered_aggregation.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/staggered_bootstrap.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/staggered_results.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/synthetic_did.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/twfe.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/diff_diff/utils.py +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/src/bootstrap.rs +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/src/lib.rs +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/src/linalg.rs +0 -0
- {diff_diff-2.2.0 → diff_diff-2.2.1}/rust/src/weights.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diff-diff
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: Intended Audience :: Science/Research
|
|
6
6
|
Classifier: Operating System :: OS Independent
|
|
@@ -18,6 +18,7 @@ Requires-Dist: pytest-cov>=4.0 ; extra == 'dev'
|
|
|
18
18
|
Requires-Dist: black>=23.0 ; extra == 'dev'
|
|
19
19
|
Requires-Dist: ruff>=0.1.0 ; extra == 'dev'
|
|
20
20
|
Requires-Dist: mypy>=1.0 ; extra == 'dev'
|
|
21
|
+
Requires-Dist: maturin>=1.4,<2.0 ; extra == 'dev'
|
|
21
22
|
Requires-Dist: sphinx>=6.0 ; extra == 'docs'
|
|
22
23
|
Requires-Dist: sphinx-rtd-theme>=1.0 ; extra == 'docs'
|
|
23
24
|
Provides-Extra: dev
|
|
@@ -596,12 +597,13 @@ results = twfe.fit(
|
|
|
596
597
|
|
|
597
598
|
### Multi-Period DiD (Event Study)
|
|
598
599
|
|
|
599
|
-
For settings with multiple pre- and post-treatment periods
|
|
600
|
+
For settings with multiple pre- and post-treatment periods. Estimates treatment × period
|
|
601
|
+
interactions for ALL periods (pre and post), enabling parallel trends assessment:
|
|
600
602
|
|
|
601
603
|
```python
|
|
602
604
|
from diff_diff import MultiPeriodDiD
|
|
603
605
|
|
|
604
|
-
# Fit with
|
|
606
|
+
# Fit full event study with pre and post period effects
|
|
605
607
|
did = MultiPeriodDiD()
|
|
606
608
|
results = did.fit(
|
|
607
609
|
panel_data,
|
|
@@ -609,18 +611,23 @@ results = did.fit(
|
|
|
609
611
|
treatment='treated',
|
|
610
612
|
time='period',
|
|
611
613
|
post_periods=[3, 4, 5], # Periods 3-5 are post-treatment
|
|
612
|
-
reference_period=
|
|
614
|
+
reference_period=2, # Last pre-period (e=-1 convention)
|
|
615
|
+
unit='unit_id', # Optional: warns if staggered adoption detected
|
|
613
616
|
)
|
|
614
617
|
|
|
615
|
-
#
|
|
616
|
-
for period, effect in results.
|
|
617
|
-
print(f"
|
|
618
|
+
# Pre-period effects test parallel trends (should be ≈ 0)
|
|
619
|
+
for period, effect in results.pre_period_effects.items():
|
|
620
|
+
print(f"Pre {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
|
|
621
|
+
|
|
622
|
+
# Post-period effects estimate dynamic treatment effects
|
|
623
|
+
for period, effect in results.post_period_effects.items():
|
|
624
|
+
print(f"Post {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
|
|
618
625
|
|
|
619
626
|
# View average treatment effect across post-periods
|
|
620
627
|
print(f"Average ATT: {results.avg_att:.3f}")
|
|
621
628
|
print(f"Average SE: {results.avg_se:.3f}")
|
|
622
629
|
|
|
623
|
-
# Full summary with
|
|
630
|
+
# Full summary with pre and post period effects
|
|
624
631
|
results.print_summary()
|
|
625
632
|
```
|
|
626
633
|
|
|
@@ -986,10 +993,10 @@ Create publication-ready event study plots:
|
|
|
986
993
|
```python
|
|
987
994
|
from diff_diff import plot_event_study, MultiPeriodDiD, CallawaySantAnna, SunAbraham
|
|
988
995
|
|
|
989
|
-
# From MultiPeriodDiD
|
|
996
|
+
# From MultiPeriodDiD (full event study with pre and post period effects)
|
|
990
997
|
did = MultiPeriodDiD()
|
|
991
998
|
results = did.fit(data, outcome='y', treatment='treated',
|
|
992
|
-
time='period', post_periods=[3, 4, 5])
|
|
999
|
+
time='period', post_periods=[3, 4, 5], reference_period=2)
|
|
993
1000
|
plot_event_study(results, title="Treatment Effects Over Time")
|
|
994
1001
|
|
|
995
1002
|
# From CallawaySantAnna (with event study aggregation)
|
|
@@ -1309,7 +1316,6 @@ TROP(
|
|
|
1309
1316
|
max_iter=100, # Max iterations for factor estimation
|
|
1310
1317
|
tol=1e-6, # Convergence tolerance
|
|
1311
1318
|
alpha=0.05, # Significance level
|
|
1312
|
-
variance_method='bootstrap', # 'bootstrap' or 'jackknife'
|
|
1313
1319
|
n_bootstrap=200, # Bootstrap replications
|
|
1314
1320
|
seed=None # Random seed
|
|
1315
1321
|
)
|
|
@@ -1449,14 +1455,15 @@ Pre-trends tests have low power and can exacerbate bias. **Honest DiD** (Rambach
|
|
|
1449
1455
|
```python
|
|
1450
1456
|
from diff_diff import HonestDiD, MultiPeriodDiD
|
|
1451
1457
|
|
|
1452
|
-
# First, fit a
|
|
1458
|
+
# First, fit a full event study (pre + post period effects)
|
|
1453
1459
|
did = MultiPeriodDiD()
|
|
1454
1460
|
event_results = did.fit(
|
|
1455
1461
|
data,
|
|
1456
1462
|
outcome='outcome',
|
|
1457
1463
|
treatment='treated',
|
|
1458
1464
|
time='period',
|
|
1459
|
-
post_periods=[5, 6, 7, 8, 9]
|
|
1465
|
+
post_periods=[5, 6, 7, 8, 9],
|
|
1466
|
+
reference_period=4, # Last pre-period (e=-1 convention)
|
|
1460
1467
|
)
|
|
1461
1468
|
|
|
1462
1469
|
# Compute honest bounds with relative magnitudes restriction
|
|
@@ -1524,14 +1531,15 @@ A passing pre-trends test doesn't mean parallel trends holds—it may just mean
|
|
|
1524
1531
|
```python
|
|
1525
1532
|
from diff_diff import PreTrendsPower, MultiPeriodDiD
|
|
1526
1533
|
|
|
1527
|
-
# First, fit
|
|
1534
|
+
# First, fit a full event study
|
|
1528
1535
|
did = MultiPeriodDiD()
|
|
1529
1536
|
event_results = did.fit(
|
|
1530
1537
|
data,
|
|
1531
1538
|
outcome='outcome',
|
|
1532
1539
|
treatment='treated',
|
|
1533
1540
|
time='period',
|
|
1534
|
-
post_periods=[5, 6, 7, 8, 9]
|
|
1541
|
+
post_periods=[5, 6, 7, 8, 9],
|
|
1542
|
+
reference_period=4,
|
|
1535
1543
|
)
|
|
1536
1544
|
|
|
1537
1545
|
# Analyze pre-trends test power
|
|
@@ -1800,7 +1808,8 @@ MultiPeriodDiD(
|
|
|
1800
1808
|
| `covariates` | list | Linear control variables |
|
|
1801
1809
|
| `fixed_effects` | list | Categorical FE columns (creates dummies) |
|
|
1802
1810
|
| `absorb` | list | High-dimensional FE (within-transformation) |
|
|
1803
|
-
| `reference_period` | any | Omitted period
|
|
1811
|
+
| `reference_period` | any | Omitted period (default: last pre-period, e=-1 convention) |
|
|
1812
|
+
| `unit` | str | Unit identifier column (for staggered adoption warning) |
|
|
1804
1813
|
|
|
1805
1814
|
### MultiPeriodDiDResults
|
|
1806
1815
|
|
|
@@ -1808,8 +1817,8 @@ MultiPeriodDiD(
|
|
|
1808
1817
|
|
|
1809
1818
|
| Attribute | Description |
|
|
1810
1819
|
|-----------|-------------|
|
|
1811
|
-
| `period_effects` | Dict mapping periods to PeriodEffect objects |
|
|
1812
|
-
| `avg_att` | Average ATT across post-treatment periods |
|
|
1820
|
+
| `period_effects` | Dict mapping periods to PeriodEffect objects (pre and post, excluding reference) |
|
|
1821
|
+
| `avg_att` | Average ATT across post-treatment periods only |
|
|
1813
1822
|
| `avg_se` | Standard error of average ATT |
|
|
1814
1823
|
| `avg_t_stat` | T-statistic for average ATT |
|
|
1815
1824
|
| `avg_p_value` | P-value for average ATT |
|
|
@@ -1817,6 +1826,10 @@ MultiPeriodDiD(
|
|
|
1817
1826
|
| `n_obs` | Number of observations |
|
|
1818
1827
|
| `pre_periods` | List of pre-treatment periods |
|
|
1819
1828
|
| `post_periods` | List of post-treatment periods |
|
|
1829
|
+
| `reference_period` | The omitted reference period (coefficient = 0 by construction) |
|
|
1830
|
+
| `interaction_indices` | Dict mapping period → column index in VCV (for sub-VCV extraction) |
|
|
1831
|
+
| `pre_period_effects` | Property: pre-period effects only (for parallel trends assessment) |
|
|
1832
|
+
| `post_period_effects` | Property: post-period effects only |
|
|
1820
1833
|
|
|
1821
1834
|
**Methods:**
|
|
1822
1835
|
|
|
@@ -1909,8 +1922,7 @@ TROP(
|
|
|
1909
1922
|
max_iter=100, # Max iterations for factor estimation
|
|
1910
1923
|
tol=1e-6, # Convergence tolerance
|
|
1911
1924
|
alpha=0.05, # Significance level for CIs
|
|
1912
|
-
|
|
1913
|
-
n_bootstrap=200, # Bootstrap/jackknife iterations
|
|
1925
|
+
n_bootstrap=200, # Bootstrap replications
|
|
1914
1926
|
seed=None # Random seed
|
|
1915
1927
|
)
|
|
1916
1928
|
```
|
|
@@ -1934,7 +1946,7 @@ Note: TROP infers treatment periods from the treatment indicator column. The tre
|
|
|
1934
1946
|
| Attribute | Description |
|
|
1935
1947
|
|-----------|-------------|
|
|
1936
1948
|
| `att` | Average Treatment effect on the Treated |
|
|
1937
|
-
| `se` | Standard error (bootstrap
|
|
1949
|
+
| `se` | Standard error (bootstrap) |
|
|
1938
1950
|
| `t_stat` | T-statistic |
|
|
1939
1951
|
| `p_value` | P-value |
|
|
1940
1952
|
| `conf_int` | Confidence interval |
|
|
@@ -1953,7 +1965,6 @@ Note: TROP infers treatment periods from the treatment indicator column. The tre
|
|
|
1953
1965
|
| `loocv_score` | LOOCV score for selected parameters |
|
|
1954
1966
|
| `n_pre_periods` | Number of pre-treatment periods |
|
|
1955
1967
|
| `n_post_periods` | Number of post-treatment periods |
|
|
1956
|
-
| `variance_method` | Variance estimation method |
|
|
1957
1968
|
| `bootstrap_distribution` | Bootstrap distribution (if bootstrap) |
|
|
1958
1969
|
|
|
1959
1970
|
**Methods:**
|
|
@@ -561,12 +561,13 @@ results = twfe.fit(
|
|
|
561
561
|
|
|
562
562
|
### Multi-Period DiD (Event Study)
|
|
563
563
|
|
|
564
|
-
For settings with multiple pre- and post-treatment periods
|
|
564
|
+
For settings with multiple pre- and post-treatment periods. Estimates treatment × period
|
|
565
|
+
interactions for ALL periods (pre and post), enabling parallel trends assessment:
|
|
565
566
|
|
|
566
567
|
```python
|
|
567
568
|
from diff_diff import MultiPeriodDiD
|
|
568
569
|
|
|
569
|
-
# Fit with
|
|
570
|
+
# Fit full event study with pre and post period effects
|
|
570
571
|
did = MultiPeriodDiD()
|
|
571
572
|
results = did.fit(
|
|
572
573
|
panel_data,
|
|
@@ -574,18 +575,23 @@ results = did.fit(
|
|
|
574
575
|
treatment='treated',
|
|
575
576
|
time='period',
|
|
576
577
|
post_periods=[3, 4, 5], # Periods 3-5 are post-treatment
|
|
577
|
-
reference_period=
|
|
578
|
+
reference_period=2, # Last pre-period (e=-1 convention)
|
|
579
|
+
unit='unit_id', # Optional: warns if staggered adoption detected
|
|
578
580
|
)
|
|
579
581
|
|
|
580
|
-
#
|
|
581
|
-
for period, effect in results.
|
|
582
|
-
print(f"
|
|
582
|
+
# Pre-period effects test parallel trends (should be ≈ 0)
|
|
583
|
+
for period, effect in results.pre_period_effects.items():
|
|
584
|
+
print(f"Pre {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
|
|
585
|
+
|
|
586
|
+
# Post-period effects estimate dynamic treatment effects
|
|
587
|
+
for period, effect in results.post_period_effects.items():
|
|
588
|
+
print(f"Post {period}: {effect.effect:.3f} (SE: {effect.se:.3f})")
|
|
583
589
|
|
|
584
590
|
# View average treatment effect across post-periods
|
|
585
591
|
print(f"Average ATT: {results.avg_att:.3f}")
|
|
586
592
|
print(f"Average SE: {results.avg_se:.3f}")
|
|
587
593
|
|
|
588
|
-
# Full summary with
|
|
594
|
+
# Full summary with pre and post period effects
|
|
589
595
|
results.print_summary()
|
|
590
596
|
```
|
|
591
597
|
|
|
@@ -951,10 +957,10 @@ Create publication-ready event study plots:
|
|
|
951
957
|
```python
|
|
952
958
|
from diff_diff import plot_event_study, MultiPeriodDiD, CallawaySantAnna, SunAbraham
|
|
953
959
|
|
|
954
|
-
# From MultiPeriodDiD
|
|
960
|
+
# From MultiPeriodDiD (full event study with pre and post period effects)
|
|
955
961
|
did = MultiPeriodDiD()
|
|
956
962
|
results = did.fit(data, outcome='y', treatment='treated',
|
|
957
|
-
time='period', post_periods=[3, 4, 5])
|
|
963
|
+
time='period', post_periods=[3, 4, 5], reference_period=2)
|
|
958
964
|
plot_event_study(results, title="Treatment Effects Over Time")
|
|
959
965
|
|
|
960
966
|
# From CallawaySantAnna (with event study aggregation)
|
|
@@ -1274,7 +1280,6 @@ TROP(
|
|
|
1274
1280
|
max_iter=100, # Max iterations for factor estimation
|
|
1275
1281
|
tol=1e-6, # Convergence tolerance
|
|
1276
1282
|
alpha=0.05, # Significance level
|
|
1277
|
-
variance_method='bootstrap', # 'bootstrap' or 'jackknife'
|
|
1278
1283
|
n_bootstrap=200, # Bootstrap replications
|
|
1279
1284
|
seed=None # Random seed
|
|
1280
1285
|
)
|
|
@@ -1414,14 +1419,15 @@ Pre-trends tests have low power and can exacerbate bias. **Honest DiD** (Rambach
|
|
|
1414
1419
|
```python
|
|
1415
1420
|
from diff_diff import HonestDiD, MultiPeriodDiD
|
|
1416
1421
|
|
|
1417
|
-
# First, fit a
|
|
1422
|
+
# First, fit a full event study (pre + post period effects)
|
|
1418
1423
|
did = MultiPeriodDiD()
|
|
1419
1424
|
event_results = did.fit(
|
|
1420
1425
|
data,
|
|
1421
1426
|
outcome='outcome',
|
|
1422
1427
|
treatment='treated',
|
|
1423
1428
|
time='period',
|
|
1424
|
-
post_periods=[5, 6, 7, 8, 9]
|
|
1429
|
+
post_periods=[5, 6, 7, 8, 9],
|
|
1430
|
+
reference_period=4, # Last pre-period (e=-1 convention)
|
|
1425
1431
|
)
|
|
1426
1432
|
|
|
1427
1433
|
# Compute honest bounds with relative magnitudes restriction
|
|
@@ -1489,14 +1495,15 @@ A passing pre-trends test doesn't mean parallel trends holds—it may just mean
|
|
|
1489
1495
|
```python
|
|
1490
1496
|
from diff_diff import PreTrendsPower, MultiPeriodDiD
|
|
1491
1497
|
|
|
1492
|
-
# First, fit
|
|
1498
|
+
# First, fit a full event study
|
|
1493
1499
|
did = MultiPeriodDiD()
|
|
1494
1500
|
event_results = did.fit(
|
|
1495
1501
|
data,
|
|
1496
1502
|
outcome='outcome',
|
|
1497
1503
|
treatment='treated',
|
|
1498
1504
|
time='period',
|
|
1499
|
-
post_periods=[5, 6, 7, 8, 9]
|
|
1505
|
+
post_periods=[5, 6, 7, 8, 9],
|
|
1506
|
+
reference_period=4,
|
|
1500
1507
|
)
|
|
1501
1508
|
|
|
1502
1509
|
# Analyze pre-trends test power
|
|
@@ -1765,7 +1772,8 @@ MultiPeriodDiD(
|
|
|
1765
1772
|
| `covariates` | list | Linear control variables |
|
|
1766
1773
|
| `fixed_effects` | list | Categorical FE columns (creates dummies) |
|
|
1767
1774
|
| `absorb` | list | High-dimensional FE (within-transformation) |
|
|
1768
|
-
| `reference_period` | any | Omitted period
|
|
1775
|
+
| `reference_period` | any | Omitted period (default: last pre-period, e=-1 convention) |
|
|
1776
|
+
| `unit` | str | Unit identifier column (for staggered adoption warning) |
|
|
1769
1777
|
|
|
1770
1778
|
### MultiPeriodDiDResults
|
|
1771
1779
|
|
|
@@ -1773,8 +1781,8 @@ MultiPeriodDiD(
|
|
|
1773
1781
|
|
|
1774
1782
|
| Attribute | Description |
|
|
1775
1783
|
|-----------|-------------|
|
|
1776
|
-
| `period_effects` | Dict mapping periods to PeriodEffect objects |
|
|
1777
|
-
| `avg_att` | Average ATT across post-treatment periods |
|
|
1784
|
+
| `period_effects` | Dict mapping periods to PeriodEffect objects (pre and post, excluding reference) |
|
|
1785
|
+
| `avg_att` | Average ATT across post-treatment periods only |
|
|
1778
1786
|
| `avg_se` | Standard error of average ATT |
|
|
1779
1787
|
| `avg_t_stat` | T-statistic for average ATT |
|
|
1780
1788
|
| `avg_p_value` | P-value for average ATT |
|
|
@@ -1782,6 +1790,10 @@ MultiPeriodDiD(
|
|
|
1782
1790
|
| `n_obs` | Number of observations |
|
|
1783
1791
|
| `pre_periods` | List of pre-treatment periods |
|
|
1784
1792
|
| `post_periods` | List of post-treatment periods |
|
|
1793
|
+
| `reference_period` | The omitted reference period (coefficient = 0 by construction) |
|
|
1794
|
+
| `interaction_indices` | Dict mapping period → column index in VCV (for sub-VCV extraction) |
|
|
1795
|
+
| `pre_period_effects` | Property: pre-period effects only (for parallel trends assessment) |
|
|
1796
|
+
| `post_period_effects` | Property: post-period effects only |
|
|
1785
1797
|
|
|
1786
1798
|
**Methods:**
|
|
1787
1799
|
|
|
@@ -1874,8 +1886,7 @@ TROP(
|
|
|
1874
1886
|
max_iter=100, # Max iterations for factor estimation
|
|
1875
1887
|
tol=1e-6, # Convergence tolerance
|
|
1876
1888
|
alpha=0.05, # Significance level for CIs
|
|
1877
|
-
|
|
1878
|
-
n_bootstrap=200, # Bootstrap/jackknife iterations
|
|
1889
|
+
n_bootstrap=200, # Bootstrap replications
|
|
1879
1890
|
seed=None # Random seed
|
|
1880
1891
|
)
|
|
1881
1892
|
```
|
|
@@ -1899,7 +1910,7 @@ Note: TROP infers treatment periods from the treatment indicator column. The tre
|
|
|
1899
1910
|
| Attribute | Description |
|
|
1900
1911
|
|-----------|-------------|
|
|
1901
1912
|
| `att` | Average Treatment effect on the Treated |
|
|
1902
|
-
| `se` | Standard error (bootstrap
|
|
1913
|
+
| `se` | Standard error (bootstrap) |
|
|
1903
1914
|
| `t_stat` | T-statistic |
|
|
1904
1915
|
| `p_value` | P-value |
|
|
1905
1916
|
| `conf_int` | Confidence interval |
|
|
@@ -1918,7 +1929,6 @@ Note: TROP infers treatment periods from the treatment indicator column. The tre
|
|
|
1918
1929
|
| `loocv_score` | LOOCV score for selected parameters |
|
|
1919
1930
|
| `n_pre_periods` | Number of pre-treatment periods |
|
|
1920
1931
|
| `n_post_periods` | Number of post-treatment periods |
|
|
1921
|
-
| `variance_method` | Variance estimation method |
|
|
1922
1932
|
| `bootstrap_distribution` | Bootstrap distribution (if bootstrap) |
|
|
1923
1933
|
|
|
1924
1934
|
**Methods:**
|
|
@@ -662,7 +662,7 @@ def permutation_test(
|
|
|
662
662
|
ci_upper = np.percentile(valid_effects, (1 - alpha / 2) * 100)
|
|
663
663
|
|
|
664
664
|
# T-stat from original estimate
|
|
665
|
-
t_stat = original_att / se if se > 0 else
|
|
665
|
+
t_stat = original_att / se if np.isfinite(se) and se > 0 else np.nan
|
|
666
666
|
|
|
667
667
|
return PlaceboTestResults(
|
|
668
668
|
test_type="permutation",
|
|
@@ -783,14 +783,14 @@ def leave_one_out_test(
|
|
|
783
783
|
# Statistics of LOO distribution
|
|
784
784
|
mean_effect = np.mean(valid_effects)
|
|
785
785
|
se = np.std(valid_effects, ddof=1) if len(valid_effects) > 1 else 0.0
|
|
786
|
-
t_stat = mean_effect / se if se > 0 else
|
|
786
|
+
t_stat = mean_effect / se if np.isfinite(se) and se > 0 else np.nan
|
|
787
787
|
|
|
788
788
|
# Use t-distribution for p-value
|
|
789
789
|
df = len(valid_effects) - 1 if len(valid_effects) > 1 else 1
|
|
790
790
|
p_value = compute_p_value(t_stat, df=df)
|
|
791
791
|
|
|
792
792
|
# CI
|
|
793
|
-
conf_int = compute_confidence_interval(mean_effect, se, alpha, df=df)
|
|
793
|
+
conf_int = compute_confidence_interval(mean_effect, se, alpha, df=df) if np.isfinite(se) and se > 0 else (np.nan, np.nan)
|
|
794
794
|
|
|
795
795
|
return PlaceboTestResults(
|
|
796
796
|
test_type="leave_one_out",
|