Diagnostics#
Placebo tests and diagnostic tools for validating DiD assumptions.
run_placebo_test#
Main dispatcher for running different types of placebo tests.
- diff_diff.run_placebo_test(data, outcome, treatment, time, unit=None, test_type='fake_timing', fake_treatment_period=None, fake_treatment_group=None, post_periods=None, n_permutations=1000, alpha=0.05, seed=None, **estimator_kwargs)[source]#
Run a placebo test to validate DiD assumptions.
Placebo tests provide evidence on the validity of the parallel trends assumption by testing whether “fake” treatments produce significant effects. A significant placebo effect suggests the parallel trends assumption may be violated.
- Parameters:
data (pd.DataFrame) – Panel data for DiD analysis.
outcome (str) – Name of outcome variable column.
treatment (str) – Name of treatment indicator column (0/1).
time (str) – Name of time period column.
unit (str, optional) – Name of unit identifier column. Required for some test types.
test_type (str, default="fake_timing") – Type of placebo test: - “fake_timing”: Assign treatment at a fake (earlier) time period - “fake_group”: Run DiD designating some control units as “fake treated” - “permutation”: Randomly reassign treatment and compute distribution - “leave_one_out”: Drop each treated unit and re-estimate
fake_treatment_period (any, optional) – For “fake_timing”: The fake treatment period to test. Should be a pre-treatment period.
fake_treatment_group (list, optional) – For “fake_group”: List of control unit IDs to designate as fake treated.
post_periods (list, optional) – List of post-treatment periods. Required for fake_timing test.
n_permutations (int, default=1000) – For “permutation”: Number of random treatment assignments.
alpha (float, default=0.05) – Significance level.
seed (int, optional) – Random seed for reproducibility.
**estimator_kwargs – Additional arguments passed to the DiD estimator.
- Returns:
Object containing placebo effect estimates, p-values, and diagnostics.
- Return type:
Examples
Fake timing test:
>>> results = run_placebo_test( ... data, outcome='sales', treatment='treated', time='period', ... test_type='fake_timing', ... fake_treatment_period=1, # Pre-treatment period ... post_periods=[2, 3, 4] ... ) >>> if results.is_significant: ... print("Warning: Pre-treatment differential trends detected!")
Permutation test:
>>> results = run_placebo_test( ... data, outcome='sales', treatment='treated', time='period', ... unit='unit_id', ... test_type='permutation', ... n_permutations=1000, ... seed=42 ... ) >>> print(f"Permutation p-value: {results.p_value:.4f}")
References
Bertrand, M., Duflo, E., & Mullainathan, S. (2004). How Much Should We Trust Differences-in-Differences Estimates? The Quarterly Journal of Economics, 119(1), 249-275.
placebo_timing_test#
Test using fake treatment timing.
- diff_diff.placebo_timing_test(data, outcome, treatment, time, fake_treatment_period, post_periods=None, alpha=0.05, **estimator_kwargs)[source]#
Test for pre-treatment effects by moving treatment timing earlier.
Creates a fake “post” indicator using pre-treatment data only, then estimates a DiD model. A significant effect suggests pre-existing differential trends.
- Parameters:
data (pd.DataFrame) – Panel data.
outcome (str) – Outcome variable column.
treatment (str) – Treatment indicator column.
time (str) – Time period column.
fake_treatment_period (any) – Period to use as fake treatment timing (should be a pre-treatment period).
post_periods (list, optional) – List of actual post-treatment periods. If None, infers from data.
alpha (float, default=0.05) – Significance level.
**estimator_kwargs – Arguments passed to DifferenceInDifferences.
- Returns:
Results of the fake timing placebo test.
- Return type:
Example#
from diff_diff import placebo_timing_test
# Test if effect exists at a fake treatment time
result = placebo_timing_test(
data,
outcome='y',
treatment='treated',
time='period',
fake_treatment_period=3 # Test earlier period
)
print(f"Placebo effect: {result.placebo_effect:.3f}")
print(f"p-value: {result.p_value:.3f}")
placebo_group_test#
Test using fake treatment groups (DiD on never-treated).
- diff_diff.placebo_group_test(data, outcome, time, unit, fake_treated_units, post_periods=None, alpha=0.05, **estimator_kwargs)[source]#
Test for differential trends among never-treated units.
Assigns some never-treated units as “fake treated” and estimates a DiD model using only never-treated data. A significant effect suggests heterogeneous trends in the control group.
- Parameters:
data (pd.DataFrame) – Panel data.
outcome (str) – Outcome variable column.
time (str) – Time period column.
unit (str) – Unit identifier column.
fake_treated_units (list) – List of control unit IDs to designate as “fake treated”.
post_periods (list, optional) – List of post-treatment period values.
alpha (float, default=0.05) – Significance level.
**estimator_kwargs – Arguments passed to DifferenceInDifferences.
- Returns:
Results of the fake group placebo test.
- Return type:
Example#
from diff_diff import placebo_group_test
# Run DiD among never-treated units
result = placebo_group_test(
data,
outcome='y',
time='period',
unit='unit_id',
fake_treated_units=[10, 11, 12] # Assign some control units as fake-treated
)
# Should find no effect if parallel trends holds
print(f"Placebo effect: {result.placebo_effect:.3f}")
permutation_test#
Permutation-based inference for treatment effects.
- diff_diff.permutation_test(data, outcome, treatment, time, unit, n_permutations=1000, alpha=0.05, seed=None, **estimator_kwargs)[source]#
Compute permutation-based p-value for DiD estimate.
Randomly reassigns treatment status at the unit level and computes the DiD estimate for each permutation. The p-value is the proportion of permuted estimates at least as extreme as the original.
- Parameters:
data (pd.DataFrame) – Panel data.
outcome (str) – Outcome variable column.
treatment (str) – Treatment indicator column.
time (str) – Time period column.
unit (str) – Unit identifier column.
n_permutations (int, default=1000) – Number of random permutations.
alpha (float, default=0.05) – Significance level.
seed (int, optional) – Random seed for reproducibility.
**estimator_kwargs – Arguments passed to DifferenceInDifferences.
- Returns:
Results with permutation distribution and p-value.
- Return type:
Notes
The permutation test is exact and does not rely on asymptotic approximations, making it valid with any sample size.
Example#
from diff_diff import permutation_test, generate_did_data
panel = generate_did_data(n_units=100, n_periods=10, treatment_effect=2.0)
result = permutation_test(
panel,
outcome='outcome',
treatment='treated',
time='post',
unit='unit',
n_permutations=1000
)
print(f"Permutation p-value: {result.p_value:.3f}")
leave_one_out_test#
Sensitivity analysis removing individual treated units.
- diff_diff.leave_one_out_test(data, outcome, treatment, time, unit, alpha=0.05, **estimator_kwargs)[source]#
Assess sensitivity by dropping each treated unit in turn.
For each treated unit, drops that unit and re-estimates the DiD model. Large variation in estimates suggests results are driven by a single unit.
- Parameters:
data (pd.DataFrame) – Panel data.
outcome (str) – Outcome variable column.
treatment (str) – Treatment indicator column.
time (str) – Time period column.
unit (str) – Unit identifier column.
alpha (float, default=0.05) – Significance level.
**estimator_kwargs – Arguments passed to DifferenceInDifferences.
- Returns:
Results with leave_one_out_effects dict mapping unit -> ATT estimate.
- Return type:
Example#
from diff_diff import leave_one_out_test, generate_did_data
panel = generate_did_data(n_units=100, n_periods=10, treatment_effect=2.0)
result = leave_one_out_test(
panel,
outcome='outcome',
treatment='treated',
time='post',
unit='unit'
)
# Check if results are driven by single units
loo = result.leave_one_out_effects
print(f"Effect range: [{min(loo.values()):.3f}, {max(loo.values()):.3f}]")
run_all_placebo_tests#
Run comprehensive suite of diagnostic tests.
- diff_diff.run_all_placebo_tests(data, outcome, treatment, time, unit, pre_periods, post_periods, n_permutations=500, alpha=0.05, seed=None, **estimator_kwargs)[source]#
Run a comprehensive suite of placebo tests.
Runs fake timing tests for each pre-period, a permutation test, and a leave-one-out sensitivity analysis. If a test fails, the result will be a dict with an “error” key containing the error message.
- Parameters:
data (pd.DataFrame) – Panel data.
outcome (str) – Outcome variable column.
treatment (str) – Treatment indicator column.
time (str) – Time period column.
unit (str) – Unit identifier column.
pre_periods (list) – List of pre-treatment periods.
post_periods (list) – List of post-treatment periods.
n_permutations (int, default=500) – Permutations for permutation test.
alpha (float, default=0.05) – Significance level.
seed (int, optional) – Random seed.
**estimator_kwargs – Arguments passed to estimators.
- Returns:
Dictionary mapping test names to PlaceboTestResults. Keys: “fake_timing_{period}”, “permutation”, “leave_one_out”
- Return type:
PlaceboTestResults#
Container for placebo test results.
- class diff_diff.PlaceboTestResults[source]
Bases:
objectResults from a placebo test for DiD assumption validation.
- test_type
Type of placebo test performed.
- Type:
- placebo_effect
Estimated placebo treatment effect.
- Type:
- se
Standard error of the placebo effect.
- Type:
- t_stat
T-statistic for the placebo effect.
- Type:
- p_value
P-value for testing placebo_effect = 0.
- Type:
- conf_int
Confidence interval for the placebo effect.
- Type:
- n_obs
Number of observations used in the test.
- Type:
- is_significant
Whether the placebo effect is significant at alpha=0.05.
- Type:
- original_effect
Original ATT estimate for comparison.
- Type:
float, optional
- original_se
Original SE for comparison.
- Type:
float, optional
- permutation_distribution
Distribution of permuted effects (for permutation test).
- Type:
np.ndarray, optional
- leave_one_out_effects
Unit-specific effects (for leave-one-out test).
- Type:
dict, optional
- fake_period
The fake treatment period used (for timing test).
- Type:
any, optional
- fake_group
The fake treatment group used (for group test).
- Type:
list, optional
- test_type: str
- placebo_effect: float
- se: float
- t_stat: float
- p_value: float
- n_obs: int
- is_significant: bool
- alpha: float = 0.05
- property significance_stars: str
Return significance stars based on p-value.
- print_summary()[source]
Print summary to stdout.
- Return type:
None
- __init__(test_type, placebo_effect, se, t_stat, p_value, conf_int, n_obs, is_significant, alpha=0.05, original_effect=None, original_se=None, permutation_distribution=None, leave_one_out_effects=None, fake_period=None, fake_group=None, n_permutations=None)
- Parameters:
- Return type:
None