diff-diff 2.1.7__tar.gz → 2.1.9__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.1.7 → diff_diff-2.1.9}/PKG-INFO +19 -9
- {diff_diff-2.1.7 → diff_diff-2.1.9}/README.md +18 -8
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/__init__.py +1 -1
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/_backend.py +16 -4
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/trop.py +1537 -229
- {diff_diff-2.1.7 → diff_diff-2.1.9}/pyproject.toml +1 -1
- {diff_diff-2.1.7 → diff_diff-2.1.9}/rust/Cargo.lock +7 -7
- {diff_diff-2.1.7 → diff_diff-2.1.9}/rust/Cargo.toml +1 -1
- {diff_diff-2.1.7 → diff_diff-2.1.9}/rust/src/lib.rs +5 -1
- diff_diff-2.1.9/rust/src/trop.rs +1772 -0
- diff_diff-2.1.7/rust/src/trop.rs +0 -935
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/bacon.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/datasets.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/diagnostics.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/estimators.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/honest_did.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/linalg.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/power.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/prep.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/prep_dgp.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/pretrends.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/results.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/staggered.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/staggered_aggregation.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/staggered_bootstrap.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/staggered_results.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/sun_abraham.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/synthetic_did.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/triple_diff.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/twfe.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/utils.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/diff_diff/visualization.py +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/rust/src/bootstrap.rs +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/rust/src/linalg.rs +0 -0
- {diff_diff-2.1.7 → diff_diff-2.1.9}/rust/src/weights.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diff-diff
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.9
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: Intended Audience :: Science/Research
|
|
6
6
|
Classifier: Operating System :: OS Independent
|
|
@@ -1173,13 +1173,15 @@ trop_est = TROP(
|
|
|
1173
1173
|
lambda_nn_grid=[0.0, 0.1, 1.0], # Nuclear norm grid
|
|
1174
1174
|
n_bootstrap=200
|
|
1175
1175
|
)
|
|
1176
|
+
# Note: TROP infers treatment periods from the treatment indicator column.
|
|
1177
|
+
# The 'treated' column must be an absorbing state (D=1 for all periods
|
|
1178
|
+
# during and after treatment starts for each unit).
|
|
1176
1179
|
results = trop_est.fit(
|
|
1177
1180
|
panel_data,
|
|
1178
1181
|
outcome='gdp_growth',
|
|
1179
1182
|
treatment='treated',
|
|
1180
1183
|
unit='state',
|
|
1181
|
-
time='year'
|
|
1182
|
-
post_periods=[2015, 2016, 2017, 2018]
|
|
1184
|
+
time='year'
|
|
1183
1185
|
)
|
|
1184
1186
|
|
|
1185
1187
|
# View results
|
|
@@ -1267,9 +1269,11 @@ sdid_results = sdid.fit(data, outcome='y', treatment='treated',
|
|
|
1267
1269
|
unit='unit', time='time', post_periods=[5,6,7])
|
|
1268
1270
|
|
|
1269
1271
|
# TROP (accounts for factors)
|
|
1272
|
+
# Note: TROP infers treatment periods from the treatment indicator column
|
|
1273
|
+
# (D=1 for treated observations, D=0 for control)
|
|
1270
1274
|
trop_est = TROP() # Uses default grids with LOOCV selection
|
|
1271
1275
|
trop_results = trop_est.fit(data, outcome='y', treatment='treated',
|
|
1272
|
-
unit='unit', time='time'
|
|
1276
|
+
unit='unit', time='time')
|
|
1273
1277
|
|
|
1274
1278
|
print(f"SDID estimate: {sdid_results.att:.3f}")
|
|
1275
1279
|
print(f"TROP estimate: {trop_results.att:.3f}")
|
|
@@ -1298,6 +1302,7 @@ trop = TROP(
|
|
|
1298
1302
|
|
|
1299
1303
|
```python
|
|
1300
1304
|
TROP(
|
|
1305
|
+
method='twostep', # Estimation method: 'twostep' (default) or 'joint'
|
|
1301
1306
|
lambda_time_grid=None, # Time decay grid (default: [0, 0.1, 0.5, 1, 2, 5])
|
|
1302
1307
|
lambda_unit_grid=None, # Unit distance grid (default: [0, 0.1, 0.5, 1, 2, 5])
|
|
1303
1308
|
lambda_nn_grid=None, # Nuclear norm grid (default: [0, 0.01, 0.1, 1, 10])
|
|
@@ -1310,17 +1315,21 @@ TROP(
|
|
|
1310
1315
|
)
|
|
1311
1316
|
```
|
|
1312
1317
|
|
|
1318
|
+
**Estimation methods:**
|
|
1319
|
+
- `'twostep'` (default): Per-observation model fitting following Algorithm 2 of the paper. Computes observation-specific weights and fits a model for each treated observation, then averages the individual treatment effects. More flexible but computationally intensive.
|
|
1320
|
+
- `'joint'`: Joint weighted least squares optimization. Estimates a single scalar treatment effect τ along with fixed effects and optional low-rank factor adjustment. Faster but assumes homogeneous treatment effects.
|
|
1321
|
+
|
|
1313
1322
|
**Convenience function:**
|
|
1314
1323
|
|
|
1315
1324
|
```python
|
|
1316
1325
|
# One-liner estimation with default tuning grids
|
|
1326
|
+
# Note: TROP infers treatment periods from the treatment indicator
|
|
1317
1327
|
results = trop(
|
|
1318
1328
|
data,
|
|
1319
1329
|
outcome='y',
|
|
1320
1330
|
treatment='treated',
|
|
1321
1331
|
unit='unit',
|
|
1322
1332
|
time='time',
|
|
1323
|
-
post_periods=[5, 6, 7],
|
|
1324
1333
|
n_bootstrap=200
|
|
1325
1334
|
)
|
|
1326
1335
|
```
|
|
@@ -1912,10 +1921,11 @@ TROP(
|
|
|
1912
1921
|
|-----------|------|-------------|
|
|
1913
1922
|
| `data` | DataFrame | Panel data |
|
|
1914
1923
|
| `outcome` | str | Outcome variable column name |
|
|
1915
|
-
| `treatment` | str | Treatment indicator column (0/1) |
|
|
1924
|
+
| `treatment` | str | Treatment indicator column (0/1 absorbing state) |
|
|
1916
1925
|
| `unit` | str | Unit identifier column |
|
|
1917
1926
|
| `time` | str | Time period column |
|
|
1918
|
-
|
|
1927
|
+
|
|
1928
|
+
Note: TROP infers treatment periods from the treatment indicator column. The treatment column should be an absorbing state indicator where D=1 for all periods during and after treatment starts.
|
|
1919
1929
|
|
|
1920
1930
|
### TROPResults
|
|
1921
1931
|
|
|
@@ -1941,8 +1951,8 @@ TROP(
|
|
|
1941
1951
|
| `factor_matrix` | Low-rank factor matrix L (n_periods x n_units) |
|
|
1942
1952
|
| `effective_rank` | Effective rank of factor matrix |
|
|
1943
1953
|
| `loocv_score` | LOOCV score for selected parameters |
|
|
1944
|
-
| `
|
|
1945
|
-
| `
|
|
1954
|
+
| `n_pre_periods` | Number of pre-treatment periods |
|
|
1955
|
+
| `n_post_periods` | Number of post-treatment periods |
|
|
1946
1956
|
| `variance_method` | Variance estimation method |
|
|
1947
1957
|
| `bootstrap_distribution` | Bootstrap distribution (if bootstrap) |
|
|
1948
1958
|
|
|
@@ -1138,13 +1138,15 @@ trop_est = TROP(
|
|
|
1138
1138
|
lambda_nn_grid=[0.0, 0.1, 1.0], # Nuclear norm grid
|
|
1139
1139
|
n_bootstrap=200
|
|
1140
1140
|
)
|
|
1141
|
+
# Note: TROP infers treatment periods from the treatment indicator column.
|
|
1142
|
+
# The 'treated' column must be an absorbing state (D=1 for all periods
|
|
1143
|
+
# during and after treatment starts for each unit).
|
|
1141
1144
|
results = trop_est.fit(
|
|
1142
1145
|
panel_data,
|
|
1143
1146
|
outcome='gdp_growth',
|
|
1144
1147
|
treatment='treated',
|
|
1145
1148
|
unit='state',
|
|
1146
|
-
time='year'
|
|
1147
|
-
post_periods=[2015, 2016, 2017, 2018]
|
|
1149
|
+
time='year'
|
|
1148
1150
|
)
|
|
1149
1151
|
|
|
1150
1152
|
# View results
|
|
@@ -1232,9 +1234,11 @@ sdid_results = sdid.fit(data, outcome='y', treatment='treated',
|
|
|
1232
1234
|
unit='unit', time='time', post_periods=[5,6,7])
|
|
1233
1235
|
|
|
1234
1236
|
# TROP (accounts for factors)
|
|
1237
|
+
# Note: TROP infers treatment periods from the treatment indicator column
|
|
1238
|
+
# (D=1 for treated observations, D=0 for control)
|
|
1235
1239
|
trop_est = TROP() # Uses default grids with LOOCV selection
|
|
1236
1240
|
trop_results = trop_est.fit(data, outcome='y', treatment='treated',
|
|
1237
|
-
unit='unit', time='time'
|
|
1241
|
+
unit='unit', time='time')
|
|
1238
1242
|
|
|
1239
1243
|
print(f"SDID estimate: {sdid_results.att:.3f}")
|
|
1240
1244
|
print(f"TROP estimate: {trop_results.att:.3f}")
|
|
@@ -1263,6 +1267,7 @@ trop = TROP(
|
|
|
1263
1267
|
|
|
1264
1268
|
```python
|
|
1265
1269
|
TROP(
|
|
1270
|
+
method='twostep', # Estimation method: 'twostep' (default) or 'joint'
|
|
1266
1271
|
lambda_time_grid=None, # Time decay grid (default: [0, 0.1, 0.5, 1, 2, 5])
|
|
1267
1272
|
lambda_unit_grid=None, # Unit distance grid (default: [0, 0.1, 0.5, 1, 2, 5])
|
|
1268
1273
|
lambda_nn_grid=None, # Nuclear norm grid (default: [0, 0.01, 0.1, 1, 10])
|
|
@@ -1275,17 +1280,21 @@ TROP(
|
|
|
1275
1280
|
)
|
|
1276
1281
|
```
|
|
1277
1282
|
|
|
1283
|
+
**Estimation methods:**
|
|
1284
|
+
- `'twostep'` (default): Per-observation model fitting following Algorithm 2 of the paper. Computes observation-specific weights and fits a model for each treated observation, then averages the individual treatment effects. More flexible but computationally intensive.
|
|
1285
|
+
- `'joint'`: Joint weighted least squares optimization. Estimates a single scalar treatment effect τ along with fixed effects and optional low-rank factor adjustment. Faster but assumes homogeneous treatment effects.
|
|
1286
|
+
|
|
1278
1287
|
**Convenience function:**
|
|
1279
1288
|
|
|
1280
1289
|
```python
|
|
1281
1290
|
# One-liner estimation with default tuning grids
|
|
1291
|
+
# Note: TROP infers treatment periods from the treatment indicator
|
|
1282
1292
|
results = trop(
|
|
1283
1293
|
data,
|
|
1284
1294
|
outcome='y',
|
|
1285
1295
|
treatment='treated',
|
|
1286
1296
|
unit='unit',
|
|
1287
1297
|
time='time',
|
|
1288
|
-
post_periods=[5, 6, 7],
|
|
1289
1298
|
n_bootstrap=200
|
|
1290
1299
|
)
|
|
1291
1300
|
```
|
|
@@ -1877,10 +1886,11 @@ TROP(
|
|
|
1877
1886
|
|-----------|------|-------------|
|
|
1878
1887
|
| `data` | DataFrame | Panel data |
|
|
1879
1888
|
| `outcome` | str | Outcome variable column name |
|
|
1880
|
-
| `treatment` | str | Treatment indicator column (0/1) |
|
|
1889
|
+
| `treatment` | str | Treatment indicator column (0/1 absorbing state) |
|
|
1881
1890
|
| `unit` | str | Unit identifier column |
|
|
1882
1891
|
| `time` | str | Time period column |
|
|
1883
|
-
|
|
1892
|
+
|
|
1893
|
+
Note: TROP infers treatment periods from the treatment indicator column. The treatment column should be an absorbing state indicator where D=1 for all periods during and after treatment starts.
|
|
1884
1894
|
|
|
1885
1895
|
### TROPResults
|
|
1886
1896
|
|
|
@@ -1906,8 +1916,8 @@ TROP(
|
|
|
1906
1916
|
| `factor_matrix` | Low-rank factor matrix L (n_periods x n_units) |
|
|
1907
1917
|
| `effective_rank` | Effective rank of factor matrix |
|
|
1908
1918
|
| `loocv_score` | LOOCV score for selected parameters |
|
|
1909
|
-
| `
|
|
1910
|
-
| `
|
|
1919
|
+
| `n_pre_periods` | Number of pre-treatment periods |
|
|
1920
|
+
| `n_post_periods` | Number of post-treatment periods |
|
|
1911
1921
|
| `variance_method` | Variance estimation method |
|
|
1912
1922
|
| `bootstrap_distribution` | Bootstrap distribution (if bootstrap) |
|
|
1913
1923
|
|
|
@@ -23,10 +23,13 @@ try:
|
|
|
23
23
|
project_simplex as _rust_project_simplex,
|
|
24
24
|
solve_ols as _rust_solve_ols,
|
|
25
25
|
compute_robust_vcov as _rust_compute_robust_vcov,
|
|
26
|
-
# TROP estimator acceleration
|
|
26
|
+
# TROP estimator acceleration (twostep method)
|
|
27
27
|
compute_unit_distance_matrix as _rust_unit_distance_matrix,
|
|
28
28
|
loocv_grid_search as _rust_loocv_grid_search,
|
|
29
29
|
bootstrap_trop_variance as _rust_bootstrap_trop_variance,
|
|
30
|
+
# TROP estimator acceleration (joint method)
|
|
31
|
+
loocv_grid_search_joint as _rust_loocv_grid_search_joint,
|
|
32
|
+
bootstrap_trop_variance_joint as _rust_bootstrap_trop_variance_joint,
|
|
30
33
|
)
|
|
31
34
|
_rust_available = True
|
|
32
35
|
except ImportError:
|
|
@@ -36,10 +39,13 @@ except ImportError:
|
|
|
36
39
|
_rust_project_simplex = None
|
|
37
40
|
_rust_solve_ols = None
|
|
38
41
|
_rust_compute_robust_vcov = None
|
|
39
|
-
# TROP estimator acceleration
|
|
42
|
+
# TROP estimator acceleration (twostep method)
|
|
40
43
|
_rust_unit_distance_matrix = None
|
|
41
44
|
_rust_loocv_grid_search = None
|
|
42
45
|
_rust_bootstrap_trop_variance = None
|
|
46
|
+
# TROP estimator acceleration (joint method)
|
|
47
|
+
_rust_loocv_grid_search_joint = None
|
|
48
|
+
_rust_bootstrap_trop_variance_joint = None
|
|
43
49
|
|
|
44
50
|
# Determine final backend based on environment variable and availability
|
|
45
51
|
if _backend_env == 'python':
|
|
@@ -50,10 +56,13 @@ if _backend_env == 'python':
|
|
|
50
56
|
_rust_project_simplex = None
|
|
51
57
|
_rust_solve_ols = None
|
|
52
58
|
_rust_compute_robust_vcov = None
|
|
53
|
-
# TROP estimator acceleration
|
|
59
|
+
# TROP estimator acceleration (twostep method)
|
|
54
60
|
_rust_unit_distance_matrix = None
|
|
55
61
|
_rust_loocv_grid_search = None
|
|
56
62
|
_rust_bootstrap_trop_variance = None
|
|
63
|
+
# TROP estimator acceleration (joint method)
|
|
64
|
+
_rust_loocv_grid_search_joint = None
|
|
65
|
+
_rust_bootstrap_trop_variance_joint = None
|
|
57
66
|
elif _backend_env == 'rust':
|
|
58
67
|
# Force Rust mode - fail if not available
|
|
59
68
|
if not _rust_available:
|
|
@@ -73,8 +82,11 @@ __all__ = [
|
|
|
73
82
|
'_rust_project_simplex',
|
|
74
83
|
'_rust_solve_ols',
|
|
75
84
|
'_rust_compute_robust_vcov',
|
|
76
|
-
# TROP estimator acceleration
|
|
85
|
+
# TROP estimator acceleration (twostep method)
|
|
77
86
|
'_rust_unit_distance_matrix',
|
|
78
87
|
'_rust_loocv_grid_search',
|
|
79
88
|
'_rust_bootstrap_trop_variance',
|
|
89
|
+
# TROP estimator acceleration (joint method)
|
|
90
|
+
'_rust_loocv_grid_search_joint',
|
|
91
|
+
'_rust_bootstrap_trop_variance_joint',
|
|
80
92
|
]
|