diff-diff 2.1.8__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.
Files changed (34) hide show
  1. {diff_diff-2.1.8 → diff_diff-2.1.9}/PKG-INFO +6 -1
  2. {diff_diff-2.1.8 → diff_diff-2.1.9}/README.md +5 -0
  3. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/__init__.py +1 -1
  4. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/_backend.py +16 -4
  5. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/trop.py +1032 -30
  6. {diff_diff-2.1.8 → diff_diff-2.1.9}/pyproject.toml +1 -1
  7. {diff_diff-2.1.8 → diff_diff-2.1.9}/rust/Cargo.lock +5 -5
  8. {diff_diff-2.1.8 → diff_diff-2.1.9}/rust/Cargo.toml +1 -1
  9. {diff_diff-2.1.8 → diff_diff-2.1.9}/rust/src/lib.rs +5 -1
  10. {diff_diff-2.1.8 → diff_diff-2.1.9}/rust/src/trop.rs +665 -0
  11. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/bacon.py +0 -0
  12. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/datasets.py +0 -0
  13. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/diagnostics.py +0 -0
  14. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/estimators.py +0 -0
  15. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/honest_did.py +0 -0
  16. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/linalg.py +0 -0
  17. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/power.py +0 -0
  18. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/prep.py +0 -0
  19. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/prep_dgp.py +0 -0
  20. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/pretrends.py +0 -0
  21. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/results.py +0 -0
  22. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/staggered.py +0 -0
  23. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/staggered_aggregation.py +0 -0
  24. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/staggered_bootstrap.py +0 -0
  25. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/staggered_results.py +0 -0
  26. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/sun_abraham.py +0 -0
  27. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/synthetic_did.py +0 -0
  28. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/triple_diff.py +0 -0
  29. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/twfe.py +0 -0
  30. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/utils.py +0 -0
  31. {diff_diff-2.1.8 → diff_diff-2.1.9}/diff_diff/visualization.py +0 -0
  32. {diff_diff-2.1.8 → diff_diff-2.1.9}/rust/src/bootstrap.rs +0 -0
  33. {diff_diff-2.1.8 → diff_diff-2.1.9}/rust/src/linalg.rs +0 -0
  34. {diff_diff-2.1.8 → 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.8
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
@@ -1302,6 +1302,7 @@ trop = TROP(
1302
1302
 
1303
1303
  ```python
1304
1304
  TROP(
1305
+ method='twostep', # Estimation method: 'twostep' (default) or 'joint'
1305
1306
  lambda_time_grid=None, # Time decay grid (default: [0, 0.1, 0.5, 1, 2, 5])
1306
1307
  lambda_unit_grid=None, # Unit distance grid (default: [0, 0.1, 0.5, 1, 2, 5])
1307
1308
  lambda_nn_grid=None, # Nuclear norm grid (default: [0, 0.01, 0.1, 1, 10])
@@ -1314,6 +1315,10 @@ TROP(
1314
1315
  )
1315
1316
  ```
1316
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
+
1317
1322
  **Convenience function:**
1318
1323
 
1319
1324
  ```python
@@ -1267,6 +1267,7 @@ trop = TROP(
1267
1267
 
1268
1268
  ```python
1269
1269
  TROP(
1270
+ method='twostep', # Estimation method: 'twostep' (default) or 'joint'
1270
1271
  lambda_time_grid=None, # Time decay grid (default: [0, 0.1, 0.5, 1, 2, 5])
1271
1272
  lambda_unit_grid=None, # Unit distance grid (default: [0, 0.1, 0.5, 1, 2, 5])
1272
1273
  lambda_nn_grid=None, # Nuclear norm grid (default: [0, 0.01, 0.1, 1, 10])
@@ -1279,6 +1280,10 @@ TROP(
1279
1280
  )
1280
1281
  ```
1281
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
+
1282
1287
  **Convenience function:**
1283
1288
 
1284
1289
  ```python
@@ -136,7 +136,7 @@ from diff_diff.datasets import (
136
136
  load_mpdta,
137
137
  )
138
138
 
139
- __version__ = "2.1.8"
139
+ __version__ = "2.1.9"
140
140
  __all__ = [
141
141
  # Estimators
142
142
  "DifferenceInDifferences",
@@ -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
  ]