diff-diff 0.5.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

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/__init__.py CHANGED
@@ -5,16 +5,42 @@ 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.diagnostics import (
9
+ PlaceboTestResults,
10
+ leave_one_out_test,
11
+ permutation_test,
12
+ placebo_group_test,
13
+ placebo_timing_test,
14
+ run_all_placebo_tests,
15
+ run_placebo_test,
16
+ )
8
17
  from diff_diff.estimators import (
9
18
  DifferenceInDifferences,
10
- TwoWayFixedEffects,
11
19
  MultiPeriodDiD,
12
20
  SyntheticDiD,
21
+ TwoWayFixedEffects,
13
22
  )
14
- from diff_diff.staggered import (
15
- CallawaySantAnna,
16
- CallawaySantAnnaResults,
17
- GroupTimeEffect,
23
+ from diff_diff.honest_did import (
24
+ DeltaRM,
25
+ DeltaSD,
26
+ DeltaSDRM,
27
+ HonestDiD,
28
+ HonestDiDResults,
29
+ SensitivityResults,
30
+ compute_honest_did,
31
+ sensitivity_plot,
32
+ )
33
+ from diff_diff.prep import (
34
+ aggregate_to_cohorts,
35
+ balance_panel,
36
+ create_event_time,
37
+ generate_did_data,
38
+ make_post_indicator,
39
+ make_treatment_indicator,
40
+ rank_control_units,
41
+ summarize_did_data,
42
+ validate_did_data,
43
+ wide_to_long,
18
44
  )
19
45
  from diff_diff.results import (
20
46
  DiDResults,
@@ -22,40 +48,26 @@ from diff_diff.results import (
22
48
  PeriodEffect,
23
49
  SyntheticDiDResults,
24
50
  )
25
- from diff_diff.visualization import (
26
- plot_event_study,
27
- plot_group_effects,
28
- )
29
- from diff_diff.prep import (
30
- make_treatment_indicator,
31
- make_post_indicator,
32
- wide_to_long,
33
- balance_panel,
34
- validate_did_data,
35
- summarize_did_data,
36
- generate_did_data,
37
- create_event_time,
38
- aggregate_to_cohorts,
39
- rank_control_units,
51
+ from diff_diff.staggered import (
52
+ CallawaySantAnna,
53
+ CallawaySantAnnaResults,
54
+ GroupTimeEffect,
40
55
  )
41
56
  from diff_diff.utils import (
57
+ WildBootstrapResults,
42
58
  check_parallel_trends,
43
59
  check_parallel_trends_robust,
44
60
  equivalence_test_trends,
45
- WildBootstrapResults,
46
61
  wild_bootstrap_se,
47
62
  )
48
- from diff_diff.diagnostics import (
49
- PlaceboTestResults,
50
- run_placebo_test,
51
- placebo_timing_test,
52
- placebo_group_test,
53
- permutation_test,
54
- leave_one_out_test,
55
- run_all_placebo_tests,
63
+ from diff_diff.visualization import (
64
+ plot_event_study,
65
+ plot_group_effects,
66
+ plot_honest_event_study,
67
+ plot_sensitivity,
56
68
  )
57
69
 
58
- __version__ = "0.5.0"
70
+ __version__ = "0.6.0"
59
71
  __all__ = [
60
72
  # Estimators
61
73
  "DifferenceInDifferences",
@@ -73,6 +85,8 @@ __all__ = [
73
85
  # Visualization
74
86
  "plot_event_study",
75
87
  "plot_group_effects",
88
+ "plot_sensitivity",
89
+ "plot_honest_event_study",
76
90
  # Parallel trends testing
77
91
  "check_parallel_trends",
78
92
  "check_parallel_trends_robust",
@@ -99,4 +113,13 @@ __all__ = [
99
113
  "create_event_time",
100
114
  "aggregate_to_cohorts",
101
115
  "rank_control_units",
116
+ # Honest DiD sensitivity analysis
117
+ "HonestDiD",
118
+ "HonestDiDResults",
119
+ "SensitivityResults",
120
+ "DeltaSD",
121
+ "DeltaRM",
122
+ "DeltaSDRM",
123
+ "compute_honest_did",
124
+ "sensitivity_plot",
102
125
  ]
diff_diff/diagnostics.py CHANGED
@@ -360,6 +360,9 @@ def run_placebo_test(
360
360
  **estimator_kwargs
361
361
  )
362
362
 
363
+ # This should never be reached due to validation above
364
+ raise ValueError(f"Unknown test type: {test_type}")
365
+
363
366
 
364
367
  def placebo_timing_test(
365
368
  data: pd.DataFrame,
diff_diff/estimators.py CHANGED
@@ -603,6 +603,7 @@ class DifferenceInDifferences:
603
603
  """
604
604
  if not self.is_fitted_:
605
605
  raise RuntimeError("Model must be fitted before calling summary()")
606
+ assert self.results_ is not None
606
607
  return self.results_.summary()
607
608
 
608
609
  def print_summary(self) -> None:
@@ -641,7 +642,7 @@ class TwoWayFixedEffects(DifferenceInDifferences):
641
642
  staggered designs.
642
643
  """
643
644
 
644
- def fit(
645
+ def fit( # type: ignore[override]
645
646
  self,
646
647
  data: pd.DataFrame,
647
648
  outcome: str,
@@ -763,7 +764,7 @@ class TwoWayFixedEffects(DifferenceInDifferences):
763
764
  n_treated=n_treated,
764
765
  n_control=n_control,
765
766
  alpha=self.alpha,
766
- coefficients={"ATT": att},
767
+ coefficients={"ATT": float(att)},
767
768
  vcov=vcov,
768
769
  residuals=residuals,
769
770
  fitted_values=fitted,
@@ -892,7 +893,7 @@ class MultiPeriodDiD(DifferenceInDifferences):
892
893
  The average ATT is computed as the mean of the δ_t coefficients.
893
894
  """
894
895
 
895
- def fit(
896
+ def fit( # type: ignore[override]
896
897
  self,
897
898
  data: pd.DataFrame,
898
899
  outcome: str,
@@ -1166,6 +1167,7 @@ class MultiPeriodDiD(DifferenceInDifferences):
1166
1167
  """
1167
1168
  if not self.is_fitted_:
1168
1169
  raise RuntimeError("Model must be fitted before calling summary()")
1170
+ assert self.results_ is not None
1169
1171
  return self.results_.summary()
1170
1172
 
1171
1173
 
@@ -1284,7 +1286,7 @@ class SyntheticDiD(DifferenceInDifferences):
1284
1286
  self._unit_weights = None
1285
1287
  self._time_weights = None
1286
1288
 
1287
- def fit(
1289
+ def fit( # type: ignore[override]
1288
1290
  self,
1289
1291
  data: pd.DataFrame,
1290
1292
  outcome: str,