diff-diff

User Guide

  • Getting Started
    • Installation
    • Basic 2x2 DiD
    • Using Formula Interface
    • Adding Covariates
    • Cluster-Robust Standard Errors
    • Two-Way Fixed Effects
    • Event Study Design
    • Staggered Adoption
    • Parallel Trends Testing
    • Sensitivity Analysis
    • Next Steps
  • Choosing an Estimator
    • Decision Flowchart
    • Quick Reference
    • Detailed Guidance
      • Basic 2x2 DiD
      • Two-Way Fixed Effects
      • Multi-Period Event Study
      • Callaway-Sant’Anna
      • Synthetic DiD
    • Common Pitfalls
    • Standard Error Methods
    • When in Doubt
  • Troubleshooting
    • Data Issues
      • “No treated observations found”
      • “Panel is unbalanced”
    • Estimation Errors
      • “Singular matrix” or “Matrix is singular”
      • “Bootstrap iterations failed” warning
    • Standard Error Issues
      • “Standard errors seem too small/large”
      • “Wild bootstrap takes too long”
    • Staggered Adoption Issues
      • “No never-treated units found”
      • “Group-time effects have large standard errors”
    • Visualization Issues
      • “Event study plot looks wrong”
      • “Plot doesn’t show in Jupyter”
    • Performance Issues
      • “Estimation is slow”
    • Getting Help
  • Comparison with R Packages
    • Overview
    • Package Correspondence
      • R did Package → diff-diff
      • R HonestDiD Package → diff-diff
      • R synthdid Package → diff-diff
    • Key Differences
      • Design Philosophy
      • Inference
      • Fixed Effects
      • Output Format
    • Feature Comparison Table
    • Migration Tips
  • Comparison with Python Packages
    • Overview
    • Package Summaries
      • pyfixest
      • differences
      • CausalPy
      • linearmodels
    • Why diff-diff?
    • Feature Comparison Table
    • Code Comparison
      • Basic DiD
      • Staggered DiD (Callaway-Sant’Anna)
      • Sensitivity Analysis
    • When to Use Each Package
  • Benchmarks: Validation Against R Packages
    • Overview
    • Methodology
      • Validation Approach
      • Tolerance Thresholds
    • Benchmark Results
      • Summary Table
      • Basic DiD Results
      • MultiPeriodDiD Results
      • Synthetic DiD Results
      • Callaway-Sant’Anna Results
    • Performance Comparison
      • Three-Way Performance Summary
      • Dataset Sizes
      • Key Observations
      • Performance Optimization Details
      • Why is diff-diff Fast?
    • Real-World Data Validation
      • MPDTA Dataset
      • Results Comparison
    • Reproducing Benchmarks
      • Prerequisites
      • Running Benchmarks
      • Output
    • Interpretation Notes
      • When to Trust Results
      • Known Differences
    • References

API Reference

  • API Reference
    • Estimators
      • diff_diff.DifferenceInDifferences
        • DifferenceInDifferences
      • diff_diff.TwoWayFixedEffects
        • TwoWayFixedEffects
      • diff_diff.MultiPeriodDiD
        • MultiPeriodDiD
      • diff_diff.SyntheticDiD
        • SyntheticDiD
      • diff_diff.CallawaySantAnna
        • CallawaySantAnna
      • diff_diff.SunAbraham
        • SunAbraham
      • diff_diff.ImputationDiD
        • ImputationDiD
      • diff_diff.StackedDiD
        • StackedDiD
      • diff_diff.TripleDifference
        • TripleDifference
      • diff_diff.TROP
        • TROP
    • Results Classes
      • diff_diff.DiDResults
        • DiDResults
      • diff_diff.MultiPeriodDiDResults
        • MultiPeriodDiDResults
      • diff_diff.SyntheticDiDResults
        • SyntheticDiDResults
      • diff_diff.PeriodEffect
        • PeriodEffect
      • diff_diff.CallawaySantAnnaResults
        • CallawaySantAnnaResults
      • diff_diff.CSBootstrapResults
        • CSBootstrapResults
      • diff_diff.GroupTimeEffect
        • GroupTimeEffect
      • diff_diff.SunAbrahamResults
        • SunAbrahamResults
      • diff_diff.SABootstrapResults
        • SABootstrapResults
      • diff_diff.ImputationDiDResults
        • ImputationDiDResults
      • diff_diff.ImputationBootstrapResults
        • ImputationBootstrapResults
      • diff_diff.TripleDifferenceResults
        • TripleDifferenceResults
      • diff_diff.StackedDiDResults
        • StackedDiDResults
      • diff_diff.trop.TROPResults
        • TROPResults
    • Visualization
      • diff_diff.plot_event_study
        • plot_event_study()
      • diff_diff.plot_group_effects
        • plot_group_effects()
      • diff_diff.plot_sensitivity
        • plot_sensitivity()
      • diff_diff.plot_honest_event_study
        • plot_honest_event_study()
      • diff_diff.plot_bacon
        • plot_bacon()
      • diff_diff.plot_power_curve
        • plot_power_curve()
      • diff_diff.plot_pretrends_power
        • plot_pretrends_power()
    • Diagnostics
      • diff_diff.run_placebo_test
        • run_placebo_test()
      • diff_diff.placebo_timing_test
        • placebo_timing_test()
      • diff_diff.placebo_group_test
        • placebo_group_test()
      • diff_diff.permutation_test
        • permutation_test()
      • diff_diff.leave_one_out_test
        • leave_one_out_test()
      • diff_diff.run_all_placebo_tests
        • run_all_placebo_tests()
      • diff_diff.PlaceboTestResults
        • PlaceboTestResults
    • Sensitivity Analysis
      • diff_diff.HonestDiD
        • HonestDiD
      • diff_diff.HonestDiDResults
        • HonestDiDResults
      • diff_diff.SensitivityResults
        • SensitivityResults
      • diff_diff.DeltaSD
        • DeltaSD
      • diff_diff.DeltaRM
        • DeltaRM
      • diff_diff.DeltaSDRM
        • DeltaSDRM
      • diff_diff.compute_honest_did
        • compute_honest_did()
      • diff_diff.sensitivity_plot
        • sensitivity_plot()
    • Parallel Trends Testing
      • diff_diff.check_parallel_trends
        • check_parallel_trends()
      • diff_diff.check_parallel_trends_robust
        • check_parallel_trends_robust()
      • diff_diff.equivalence_test_trends
        • equivalence_test_trends()
    • Bootstrap Inference
      • diff_diff.wild_bootstrap_se
        • wild_bootstrap_se()
      • diff_diff.WildBootstrapResults
        • WildBootstrapResults
    • Power Analysis
      • diff_diff.PowerAnalysis
        • PowerAnalysis
      • diff_diff.PowerResults
        • PowerResults
      • diff_diff.SimulationPowerResults
        • SimulationPowerResults
      • diff_diff.compute_power
        • compute_power()
      • diff_diff.compute_mde
        • compute_mde()
      • diff_diff.compute_sample_size
        • compute_sample_size()
      • diff_diff.simulate_power
        • simulate_power()
    • Pre-Trends Power Analysis
      • diff_diff.PreTrendsPower
        • PreTrendsPower
      • diff_diff.PreTrendsPowerResults
        • PreTrendsPowerResults
      • diff_diff.PreTrendsPowerCurve
        • PreTrendsPowerCurve
      • diff_diff.compute_pretrends_power
        • compute_pretrends_power()
      • diff_diff.compute_mdv
        • compute_mdv()
    • Data Preparation
      • diff_diff.generate_did_data
        • generate_did_data()
      • diff_diff.make_treatment_indicator
        • make_treatment_indicator()
      • diff_diff.make_post_indicator
        • make_post_indicator()
      • diff_diff.wide_to_long
        • wide_to_long()
      • diff_diff.balance_panel
        • balance_panel()
      • diff_diff.validate_did_data
        • validate_did_data()
      • diff_diff.summarize_did_data
        • summarize_did_data()
      • diff_diff.create_event_time
        • create_event_time()
      • diff_diff.aggregate_to_cohorts
        • aggregate_to_cohorts()
      • diff_diff.rank_control_units
        • rank_control_units()
    • Module Documentation
      • Estimators
        • DifferenceInDifferences
        • MultiPeriodDiD
        • TwoWayFixedEffects
        • SyntheticDiD
        • TripleDifference
      • Staggered Adoption
        • CallawaySantAnna
        • CallawaySantAnnaResults
        • GroupTimeEffect
        • SunAbraham
        • SunAbrahamResults
        • SABootstrapResults
      • Imputation DiD (Borusyak et al. 2024)
        • ImputationDiD
        • ImputationDiDResults
        • ImputationBootstrapResults
        • Convenience Function
        • Example Usage
      • Stacked Difference-in-Differences
        • StackedDiD
        • StackedDiDResults
        • Convenience Function
        • Example Usage
        • Comparison with Other Staggered Estimators
      • Triple Difference (DDD)
        • TripleDifference
        • TripleDifferenceResults
        • Convenience Function
        • Estimation Methods
        • Example Usage
      • Triply Robust Panel (TROP)
        • TROP
        • TROPResults
        • Convenience Function
        • Tuning Parameters
        • Estimation Methods
        • Example Usage
        • Comparison with Synthetic DiD
      • Results Classes
        • DiDResults
        • MultiPeriodDiDResults
        • PeriodEffect
        • SyntheticDiDResults
      • Visualization
        • plot_event_study
        • plot_group_effects
        • plot_sensitivity
        • plot_honest_event_study
      • Diagnostics
        • run_placebo_test
        • placebo_timing_test
        • placebo_group_test
        • permutation_test
        • leave_one_out_test
        • run_all_placebo_tests
        • PlaceboTestResults
      • Honest DiD
        • Overview
        • HonestDiD
        • HonestDiDResults
        • SensitivityResults
        • Restriction Classes
        • Convenience Functions
        • Complete Example
        • References
      • Power Analysis
        • Overview
        • PowerAnalysis
        • PowerResults
        • SimulationPowerResults
        • Convenience Functions
        • Complete Example
        • See Also
      • Pre-Trends Power Analysis
        • Overview
        • PreTrendsPower
        • PreTrendsPowerResults
        • PreTrendsPowerCurve
        • Convenience Functions
        • Violation Types
        • Complete Example
        • References
        • See Also
      • Utilities
        • Parallel Trends Testing
        • Wild Cluster Bootstrap
      • Data Preparation
        • Data Generation
        • Indicator Creation
        • Panel Data Utilities
        • Staggered Adoption Utilities
        • Data Validation
        • Control Unit Selection
  • Estimators
    • DifferenceInDifferences
      • DifferenceInDifferences
        • DifferenceInDifferences.results_
        • DifferenceInDifferences.is_fitted_
        • DifferenceInDifferences.__init__()
        • DifferenceInDifferences.fit()
        • DifferenceInDifferences.predict()
        • DifferenceInDifferences.get_params()
        • DifferenceInDifferences.set_params()
        • DifferenceInDifferences.summary()
        • DifferenceInDifferences.print_summary()
    • MultiPeriodDiD
      • MultiPeriodDiD
        • MultiPeriodDiD.results_
        • MultiPeriodDiD.is_fitted_
        • MultiPeriodDiD.fit()
        • MultiPeriodDiD.summary()
        • MultiPeriodDiD.__init__()
        • MultiPeriodDiD.get_params()
        • MultiPeriodDiD.predict()
        • MultiPeriodDiD.print_summary()
        • MultiPeriodDiD.set_params()
    • TwoWayFixedEffects
      • TwoWayFixedEffects
        • TwoWayFixedEffects.fit()
        • TwoWayFixedEffects.decompose()
        • TwoWayFixedEffects.__init__()
        • TwoWayFixedEffects.get_params()
        • TwoWayFixedEffects.predict()
        • TwoWayFixedEffects.print_summary()
        • TwoWayFixedEffects.set_params()
        • TwoWayFixedEffects.summary()
    • SyntheticDiD
      • SyntheticDiD
        • SyntheticDiD.results_
        • SyntheticDiD.is_fitted_
        • SyntheticDiD.__init__()
        • SyntheticDiD.fit()
        • SyntheticDiD.get_params()
        • SyntheticDiD.set_params()
        • SyntheticDiD.predict()
        • SyntheticDiD.print_summary()
        • SyntheticDiD.summary()
    • TripleDifference
      • TripleDifference
        • TripleDifference.results_
        • TripleDifference.is_fitted_
        • TripleDifference.__init__()
        • TripleDifference.results_
        • TripleDifference.fit()
        • TripleDifference.get_params()
        • TripleDifference.set_params()
        • TripleDifference.summary()
        • TripleDifference.print_summary()
      • TripleDifferenceResults
        • TripleDifferenceResults
      • Convenience Function
        • triple_difference()
  • Staggered Adoption
    • CallawaySantAnna
      • CallawaySantAnna
        • CallawaySantAnna.results_
        • CallawaySantAnna.is_fitted_
        • CallawaySantAnna.__init__()
        • CallawaySantAnna.anticipation
        • CallawaySantAnna.alpha
        • CallawaySantAnna.n_bootstrap
        • CallawaySantAnna.bootstrap_weight_type
        • CallawaySantAnna.seed
        • CallawaySantAnna.base_period
        • CallawaySantAnna.results_
        • CallawaySantAnna.fit()
        • CallawaySantAnna.get_params()
        • CallawaySantAnna.set_params()
        • CallawaySantAnna.summary()
        • CallawaySantAnna.print_summary()
    • CallawaySantAnnaResults
      • CallawaySantAnnaResults
        • CallawaySantAnnaResults.group_time_effects
        • CallawaySantAnnaResults.overall_att
        • CallawaySantAnnaResults.overall_se
        • CallawaySantAnnaResults.overall_p_value
        • CallawaySantAnnaResults.overall_conf_int
        • CallawaySantAnnaResults.groups
        • CallawaySantAnnaResults.time_periods
        • CallawaySantAnnaResults.n_obs
        • CallawaySantAnnaResults.n_treated_units
        • CallawaySantAnnaResults.n_control_units
        • CallawaySantAnnaResults.event_study_effects
        • CallawaySantAnnaResults.group_effects
        • CallawaySantAnnaResults.group_time_effects
        • CallawaySantAnnaResults.overall_att
        • CallawaySantAnnaResults.overall_se
        • CallawaySantAnnaResults.overall_t_stat
        • CallawaySantAnnaResults.overall_p_value
        • CallawaySantAnnaResults.overall_conf_int
        • CallawaySantAnnaResults.groups
        • CallawaySantAnnaResults.time_periods
        • CallawaySantAnnaResults.n_obs
        • CallawaySantAnnaResults.n_treated_units
        • CallawaySantAnnaResults.n_control_units
        • CallawaySantAnnaResults.alpha
        • CallawaySantAnnaResults.control_group
        • CallawaySantAnnaResults.base_period
        • CallawaySantAnnaResults.event_study_effects
        • CallawaySantAnnaResults.group_effects
        • CallawaySantAnnaResults.influence_functions
        • CallawaySantAnnaResults.bootstrap_results
        • CallawaySantAnnaResults.__repr__()
        • CallawaySantAnnaResults.summary()
        • CallawaySantAnnaResults.print_summary()
        • CallawaySantAnnaResults.to_dataframe()
        • CallawaySantAnnaResults.is_significant
        • CallawaySantAnnaResults.significance_stars
        • CallawaySantAnnaResults.__init__()
    • GroupTimeEffect
      • GroupTimeEffect
        • GroupTimeEffect.group
        • GroupTimeEffect.time
        • GroupTimeEffect.effect
        • GroupTimeEffect.se
        • GroupTimeEffect.n_treated
        • GroupTimeEffect.n_control
        • GroupTimeEffect.group
        • GroupTimeEffect.time
        • GroupTimeEffect.effect
        • GroupTimeEffect.se
        • GroupTimeEffect.t_stat
        • GroupTimeEffect.p_value
        • GroupTimeEffect.conf_int
        • GroupTimeEffect.n_treated
        • GroupTimeEffect.n_control
        • GroupTimeEffect.is_significant
        • GroupTimeEffect.significance_stars
        • GroupTimeEffect.__init__()
    • SunAbraham
      • SunAbraham
        • SunAbraham.results_
        • SunAbraham.is_fitted_
        • SunAbraham.__init__()
        • SunAbraham.results_
        • SunAbraham.fit()
        • SunAbraham.get_params()
        • SunAbraham.set_params()
        • SunAbraham.summary()
        • SunAbraham.print_summary()
    • SunAbrahamResults
      • SunAbrahamResults
        • SunAbrahamResults.event_study_effects
        • SunAbrahamResults.overall_att
        • SunAbrahamResults.overall_se
        • SunAbrahamResults.overall_t_stat
        • SunAbrahamResults.overall_p_value
        • SunAbrahamResults.overall_conf_int
        • SunAbrahamResults.cohort_weights
        • SunAbrahamResults.groups
        • SunAbrahamResults.time_periods
        • SunAbrahamResults.n_obs
        • SunAbrahamResults.n_treated_units
        • SunAbrahamResults.n_control_units
        • SunAbrahamResults.alpha
        • SunAbrahamResults.control_group
        • SunAbrahamResults.event_study_effects
        • SunAbrahamResults.overall_att
        • SunAbrahamResults.overall_se
        • SunAbrahamResults.overall_t_stat
        • SunAbrahamResults.overall_p_value
        • SunAbrahamResults.overall_conf_int
        • SunAbrahamResults.cohort_weights
        • SunAbrahamResults.groups
        • SunAbrahamResults.time_periods
        • SunAbrahamResults.n_obs
        • SunAbrahamResults.n_treated_units
        • SunAbrahamResults.n_control_units
        • SunAbrahamResults.alpha
        • SunAbrahamResults.control_group
        • SunAbrahamResults.bootstrap_results
        • SunAbrahamResults.cohort_effects
        • SunAbrahamResults.__repr__()
        • SunAbrahamResults.summary()
        • SunAbrahamResults.print_summary()
        • SunAbrahamResults.to_dataframe()
        • SunAbrahamResults.is_significant
        • SunAbrahamResults.significance_stars
        • SunAbrahamResults.__init__()
    • SABootstrapResults
      • SABootstrapResults
        • SABootstrapResults.n_bootstrap
        • SABootstrapResults.weight_type
        • SABootstrapResults.alpha
        • SABootstrapResults.overall_att_se
        • SABootstrapResults.overall_att_ci
        • SABootstrapResults.overall_att_p_value
        • SABootstrapResults.event_study_ses
        • SABootstrapResults.event_study_cis
        • SABootstrapResults.event_study_p_values
        • SABootstrapResults.bootstrap_distribution
        • SABootstrapResults.n_bootstrap
        • SABootstrapResults.weight_type
        • SABootstrapResults.alpha
        • SABootstrapResults.overall_att_se
        • SABootstrapResults.overall_att_ci
        • SABootstrapResults.overall_att_p_value
        • SABootstrapResults.event_study_ses
        • SABootstrapResults.event_study_cis
        • SABootstrapResults.event_study_p_values
        • SABootstrapResults.bootstrap_distribution
        • SABootstrapResults.__init__()
  • Results Classes
    • DiDResults
      • DiDResults
        • DiDResults.att
        • DiDResults.se
        • DiDResults.t_stat
        • DiDResults.p_value
        • DiDResults.conf_int
        • DiDResults.n_obs
        • DiDResults.n_treated
        • DiDResults.n_control
        • DiDResults.att
        • DiDResults.se
        • DiDResults.t_stat
        • DiDResults.p_value
        • DiDResults.conf_int
        • DiDResults.n_obs
        • DiDResults.n_treated
        • DiDResults.n_control
        • DiDResults.alpha
        • DiDResults.coefficients
        • DiDResults.vcov
        • DiDResults.residuals
        • DiDResults.fitted_values
        • DiDResults.r_squared
        • DiDResults.inference_method
        • DiDResults.n_bootstrap
        • DiDResults.n_clusters
        • DiDResults.bootstrap_distribution
        • DiDResults.__repr__()
        • DiDResults.summary()
        • DiDResults.print_summary()
        • DiDResults.to_dict()
        • DiDResults.to_dataframe()
        • DiDResults.is_significant
        • DiDResults.significance_stars
        • DiDResults.__init__()
    • MultiPeriodDiDResults
      • MultiPeriodDiDResults
        • MultiPeriodDiDResults.period_effects
        • MultiPeriodDiDResults.avg_att
        • MultiPeriodDiDResults.avg_se
        • MultiPeriodDiDResults.avg_t_stat
        • MultiPeriodDiDResults.avg_p_value
        • MultiPeriodDiDResults.avg_conf_int
        • MultiPeriodDiDResults.n_obs
        • MultiPeriodDiDResults.n_treated
        • MultiPeriodDiDResults.n_control
        • MultiPeriodDiDResults.pre_periods
        • MultiPeriodDiDResults.post_periods
        • MultiPeriodDiDResults.reference_period
        • MultiPeriodDiDResults.interaction_indices
        • MultiPeriodDiDResults.period_effects
        • MultiPeriodDiDResults.avg_att
        • MultiPeriodDiDResults.avg_se
        • MultiPeriodDiDResults.avg_t_stat
        • MultiPeriodDiDResults.avg_p_value
        • MultiPeriodDiDResults.avg_conf_int
        • MultiPeriodDiDResults.n_obs
        • MultiPeriodDiDResults.n_treated
        • MultiPeriodDiDResults.n_control
        • MultiPeriodDiDResults.pre_periods
        • MultiPeriodDiDResults.post_periods
        • MultiPeriodDiDResults.alpha
        • MultiPeriodDiDResults.coefficients
        • MultiPeriodDiDResults.vcov
        • MultiPeriodDiDResults.residuals
        • MultiPeriodDiDResults.fitted_values
        • MultiPeriodDiDResults.r_squared
        • MultiPeriodDiDResults.reference_period
        • MultiPeriodDiDResults.interaction_indices
        • MultiPeriodDiDResults.__repr__()
        • MultiPeriodDiDResults.pre_period_effects
        • MultiPeriodDiDResults.post_period_effects
        • MultiPeriodDiDResults.summary()
        • MultiPeriodDiDResults.print_summary()
        • MultiPeriodDiDResults.get_effect()
        • MultiPeriodDiDResults.to_dict()
        • MultiPeriodDiDResults.to_dataframe()
        • MultiPeriodDiDResults.is_significant
        • MultiPeriodDiDResults.significance_stars
        • MultiPeriodDiDResults.__init__()
    • PeriodEffect
      • PeriodEffect
        • PeriodEffect.period
        • PeriodEffect.effect
        • PeriodEffect.se
        • PeriodEffect.t_stat
        • PeriodEffect.p_value
        • PeriodEffect.conf_int
        • PeriodEffect.period
        • PeriodEffect.effect
        • PeriodEffect.se
        • PeriodEffect.t_stat
        • PeriodEffect.p_value
        • PeriodEffect.conf_int
        • PeriodEffect.__repr__()
        • PeriodEffect.is_significant
        • PeriodEffect.significance_stars
        • PeriodEffect.__init__()
    • SyntheticDiDResults
      • SyntheticDiDResults
        • SyntheticDiDResults.att
        • SyntheticDiDResults.se
        • SyntheticDiDResults.t_stat
        • SyntheticDiDResults.p_value
        • SyntheticDiDResults.conf_int
        • SyntheticDiDResults.n_obs
        • SyntheticDiDResults.n_treated
        • SyntheticDiDResults.n_control
        • SyntheticDiDResults.unit_weights
        • SyntheticDiDResults.time_weights
        • SyntheticDiDResults.pre_periods
        • SyntheticDiDResults.post_periods
        • SyntheticDiDResults.variance_method
        • SyntheticDiDResults.att
        • SyntheticDiDResults.se
        • SyntheticDiDResults.t_stat
        • SyntheticDiDResults.p_value
        • SyntheticDiDResults.conf_int
        • SyntheticDiDResults.n_obs
        • SyntheticDiDResults.n_treated
        • SyntheticDiDResults.n_control
        • SyntheticDiDResults.unit_weights
        • SyntheticDiDResults.time_weights
        • SyntheticDiDResults.pre_periods
        • SyntheticDiDResults.post_periods
        • SyntheticDiDResults.alpha
        • SyntheticDiDResults.variance_method
        • SyntheticDiDResults.noise_level
        • SyntheticDiDResults.zeta_omega
        • SyntheticDiDResults.zeta_lambda
        • SyntheticDiDResults.pre_treatment_fit
        • SyntheticDiDResults.placebo_effects
        • SyntheticDiDResults.n_bootstrap
        • SyntheticDiDResults.__repr__()
        • SyntheticDiDResults.summary()
        • SyntheticDiDResults.print_summary()
        • SyntheticDiDResults.to_dict()
        • SyntheticDiDResults.to_dataframe()
        • SyntheticDiDResults.get_unit_weights_df()
        • SyntheticDiDResults.get_time_weights_df()
        • SyntheticDiDResults.is_significant
        • SyntheticDiDResults.significance_stars
        • SyntheticDiDResults.__init__()
  • Visualization
    • plot_event_study
      • plot_event_study()
      • Example
    • plot_group_effects
      • plot_group_effects()
      • Example
    • plot_sensitivity
      • plot_sensitivity()
      • Example
    • plot_honest_event_study
      • plot_honest_event_study()
      • Example
  • Diagnostics
    • run_placebo_test
      • run_placebo_test()
    • placebo_timing_test
      • placebo_timing_test()
      • Example
    • placebo_group_test
      • placebo_group_test()
      • Example
    • permutation_test
      • permutation_test()
      • Example
    • leave_one_out_test
      • leave_one_out_test()
      • Example
    • run_all_placebo_tests
      • run_all_placebo_tests()
    • PlaceboTestResults
      • PlaceboTestResults
        • PlaceboTestResults.test_type
        • PlaceboTestResults.placebo_effect
        • PlaceboTestResults.se
        • PlaceboTestResults.t_stat
        • PlaceboTestResults.p_value
        • PlaceboTestResults.conf_int
        • PlaceboTestResults.n_obs
        • PlaceboTestResults.is_significant
        • PlaceboTestResults.original_effect
        • PlaceboTestResults.original_se
        • PlaceboTestResults.permutation_distribution
        • PlaceboTestResults.leave_one_out_effects
        • PlaceboTestResults.fake_period
        • PlaceboTestResults.fake_group
        • PlaceboTestResults.test_type
        • PlaceboTestResults.placebo_effect
        • PlaceboTestResults.se
        • PlaceboTestResults.t_stat
        • PlaceboTestResults.p_value
        • PlaceboTestResults.conf_int
        • PlaceboTestResults.n_obs
        • PlaceboTestResults.is_significant
        • PlaceboTestResults.alpha
        • PlaceboTestResults.original_effect
        • PlaceboTestResults.original_se
        • PlaceboTestResults.permutation_distribution
        • PlaceboTestResults.leave_one_out_effects
        • PlaceboTestResults.fake_period
        • PlaceboTestResults.fake_group
        • PlaceboTestResults.n_permutations
        • PlaceboTestResults.significance_stars
        • PlaceboTestResults.summary()
        • PlaceboTestResults.print_summary()
        • PlaceboTestResults.to_dict()
        • PlaceboTestResults.to_dataframe()
        • PlaceboTestResults.__init__()
  • Honest DiD
    • Overview
    • HonestDiD
      • HonestDiD
        • HonestDiD.__init__()
        • HonestDiD.get_params()
        • HonestDiD.set_params()
        • HonestDiD.fit()
        • HonestDiD.sensitivity_analysis()
        • HonestDiD.breakdown_value()
      • Example
    • HonestDiDResults
      • HonestDiDResults
        • HonestDiDResults.lb
        • HonestDiDResults.ub
        • HonestDiDResults.ci_lb
        • HonestDiDResults.ci_ub
        • HonestDiDResults.M
        • HonestDiDResults.method
        • HonestDiDResults.original_estimate
        • HonestDiDResults.original_se
        • HonestDiDResults.alpha
        • HonestDiDResults.ci_method
        • HonestDiDResults.original_results
        • HonestDiDResults.lb
        • HonestDiDResults.ub
        • HonestDiDResults.ci_lb
        • HonestDiDResults.ci_ub
        • HonestDiDResults.M
        • HonestDiDResults.method
        • HonestDiDResults.original_estimate
        • HonestDiDResults.original_se
        • HonestDiDResults.alpha
        • HonestDiDResults.ci_method
        • HonestDiDResults.original_results
        • HonestDiDResults.event_study_bounds
        • HonestDiDResults.is_significant
        • HonestDiDResults.significance_stars
        • HonestDiDResults.identified_set_width
        • HonestDiDResults.ci_width
        • HonestDiDResults.summary()
        • HonestDiDResults.print_summary()
        • HonestDiDResults.to_dict()
        • HonestDiDResults.to_dataframe()
        • HonestDiDResults.__init__()
    • SensitivityResults
      • SensitivityResults
        • SensitivityResults.M_values
        • SensitivityResults.bounds
        • SensitivityResults.robust_cis
        • SensitivityResults.breakdown_M
        • SensitivityResults.method
        • SensitivityResults.original_estimate
        • SensitivityResults.original_se
        • SensitivityResults.alpha
        • SensitivityResults.M_values
        • SensitivityResults.bounds
        • SensitivityResults.robust_cis
        • SensitivityResults.breakdown_M
        • SensitivityResults.method
        • SensitivityResults.original_estimate
        • SensitivityResults.original_se
        • SensitivityResults.alpha
        • SensitivityResults.has_breakdown
        • SensitivityResults.summary()
        • SensitivityResults.print_summary()
        • SensitivityResults.to_dataframe()
        • SensitivityResults.plot()
        • SensitivityResults.__init__()
    • Restriction Classes
      • DeltaSD
        • DeltaSD
      • DeltaRM
        • DeltaRM
      • DeltaSDRM
        • DeltaSDRM
    • Convenience Functions
      • compute_honest_did
        • compute_honest_did()
      • sensitivity_plot
        • sensitivity_plot()
    • Complete Example
    • References
  • Power Analysis
    • Overview
    • PowerAnalysis
      • PowerAnalysis
        • PowerAnalysis.__init__()
        • PowerAnalysis.power()
        • PowerAnalysis.mde()
        • PowerAnalysis.sample_size()
        • PowerAnalysis.power_curve()
        • PowerAnalysis.sample_size_curve()
      • Example
    • PowerResults
      • PowerResults
        • PowerResults.power
        • PowerResults.mde
        • PowerResults.required_n
        • PowerResults.effect_size
        • PowerResults.alpha
        • PowerResults.alternative
        • PowerResults.n_treated
        • PowerResults.n_control
        • PowerResults.n_pre
        • PowerResults.n_post
        • PowerResults.sigma
        • PowerResults.rho
        • PowerResults.design
        • PowerResults.power
        • PowerResults.mde
        • PowerResults.required_n
        • PowerResults.effect_size
        • PowerResults.alpha
        • PowerResults.alternative
        • PowerResults.n_treated
        • PowerResults.n_control
        • PowerResults.n_pre
        • PowerResults.n_post
        • PowerResults.sigma
        • PowerResults.rho
        • PowerResults.design
        • PowerResults.__repr__()
        • PowerResults.summary()
        • PowerResults.print_summary()
        • PowerResults.to_dict()
        • PowerResults.to_dataframe()
        • PowerResults.__init__()
    • SimulationPowerResults
      • SimulationPowerResults
        • SimulationPowerResults.power
        • SimulationPowerResults.power_se
        • SimulationPowerResults.power_ci
        • SimulationPowerResults.rejection_rate
        • SimulationPowerResults.mean_estimate
        • SimulationPowerResults.std_estimate
        • SimulationPowerResults.mean_se
        • SimulationPowerResults.coverage
        • SimulationPowerResults.n_simulations
        • SimulationPowerResults.effect_sizes
        • SimulationPowerResults.powers
        • SimulationPowerResults.true_effect
        • SimulationPowerResults.alpha
        • SimulationPowerResults.estimator_name
        • SimulationPowerResults.power
        • SimulationPowerResults.power_se
        • SimulationPowerResults.power_ci
        • SimulationPowerResults.rejection_rate
        • SimulationPowerResults.mean_estimate
        • SimulationPowerResults.std_estimate
        • SimulationPowerResults.mean_se
        • SimulationPowerResults.coverage
        • SimulationPowerResults.n_simulations
        • SimulationPowerResults.effect_sizes
        • SimulationPowerResults.powers
        • SimulationPowerResults.true_effect
        • SimulationPowerResults.alpha
        • SimulationPowerResults.estimator_name
        • SimulationPowerResults.bias
        • SimulationPowerResults.rmse
        • SimulationPowerResults.simulation_results
        • SimulationPowerResults.__post_init__()
        • SimulationPowerResults.__repr__()
        • SimulationPowerResults.summary()
        • SimulationPowerResults.print_summary()
        • SimulationPowerResults.to_dict()
        • SimulationPowerResults.to_dataframe()
        • SimulationPowerResults.power_curve_df()
        • SimulationPowerResults.__init__()
    • Convenience Functions
      • compute_power
        • compute_power()
      • compute_mde
        • compute_mde()
      • compute_sample_size
        • compute_sample_size()
      • simulate_power
        • simulate_power()
    • Complete Example
    • See Also
  • Pre-Trends Power Analysis
    • Overview
    • PreTrendsPower
      • PreTrendsPower
        • PreTrendsPower.__init__()
        • PreTrendsPower.get_params()
        • PreTrendsPower.set_params()
        • PreTrendsPower.fit()
        • PreTrendsPower.power_at()
        • PreTrendsPower.power_curve()
        • PreTrendsPower.sensitivity_to_honest_did()
      • Example
    • PreTrendsPowerResults
      • PreTrendsPowerResults
        • PreTrendsPowerResults.power
        • PreTrendsPowerResults.mdv
        • PreTrendsPowerResults.violation_magnitude
        • PreTrendsPowerResults.violation_type
        • PreTrendsPowerResults.alpha
        • PreTrendsPowerResults.target_power
        • PreTrendsPowerResults.n_pre_periods
        • PreTrendsPowerResults.test_statistic
        • PreTrendsPowerResults.critical_value
        • PreTrendsPowerResults.noncentrality
        • PreTrendsPowerResults.pre_period_effects
        • PreTrendsPowerResults.pre_period_ses
        • PreTrendsPowerResults.vcov
        • PreTrendsPowerResults.power
        • PreTrendsPowerResults.mdv
        • PreTrendsPowerResults.violation_magnitude
        • PreTrendsPowerResults.violation_type
        • PreTrendsPowerResults.alpha
        • PreTrendsPowerResults.target_power
        • PreTrendsPowerResults.n_pre_periods
        • PreTrendsPowerResults.test_statistic
        • PreTrendsPowerResults.critical_value
        • PreTrendsPowerResults.noncentrality
        • PreTrendsPowerResults.pre_period_effects
        • PreTrendsPowerResults.pre_period_ses
        • PreTrendsPowerResults.vcov
        • PreTrendsPowerResults.original_results
        • PreTrendsPowerResults.is_informative
        • PreTrendsPowerResults.power_adequate
        • PreTrendsPowerResults.summary()
        • PreTrendsPowerResults.print_summary()
        • PreTrendsPowerResults.to_dict()
        • PreTrendsPowerResults.to_dataframe()
        • PreTrendsPowerResults.power_at()
        • PreTrendsPowerResults.__init__()
    • PreTrendsPowerCurve
      • PreTrendsPowerCurve
        • PreTrendsPowerCurve.M_values
        • PreTrendsPowerCurve.powers
        • PreTrendsPowerCurve.mdv
        • PreTrendsPowerCurve.alpha
        • PreTrendsPowerCurve.target_power
        • PreTrendsPowerCurve.violation_type
        • PreTrendsPowerCurve.M_values
        • PreTrendsPowerCurve.powers
        • PreTrendsPowerCurve.mdv
        • PreTrendsPowerCurve.alpha
        • PreTrendsPowerCurve.target_power
        • PreTrendsPowerCurve.violation_type
        • PreTrendsPowerCurve.to_dataframe()
        • PreTrendsPowerCurve.plot()
        • PreTrendsPowerCurve.__init__()
    • Convenience Functions
      • compute_pretrends_power
        • compute_pretrends_power()
      • compute_mdv
        • compute_mdv()
    • Violation Types
    • Complete Example
    • References
    • See Also
  • Utilities
    • Parallel Trends Testing
      • check_parallel_trends
        • check_parallel_trends()
        • Example
      • check_parallel_trends_robust
        • check_parallel_trends_robust()
      • equivalence_test_trends
        • equivalence_test_trends()
        • Example
    • Wild Cluster Bootstrap
      • wild_bootstrap_se
        • wild_bootstrap_se()
        • Example
      • WildBootstrapResults
        • WildBootstrapResults
        • Weight Types
        • Recommendation
  • Data Preparation
    • Data Generation
      • generate_did_data
        • generate_did_data()
        • Example
    • Indicator Creation
      • make_treatment_indicator
        • make_treatment_indicator()
        • Example
      • make_post_indicator
        • make_post_indicator()
        • Example
    • Panel Data Utilities
      • wide_to_long
        • wide_to_long()
        • Example
      • balance_panel
        • balance_panel()
        • Example
    • Staggered Adoption Utilities
      • create_event_time
        • create_event_time()
        • Example
      • aggregate_to_cohorts
        • aggregate_to_cohorts()
        • Example
    • Data Validation
      • validate_did_data
        • validate_did_data()
        • Example
      • summarize_did_data
        • summarize_did_data()
        • Example
    • Control Unit Selection
      • rank_control_units
        • rank_control_units()
        • Example
diff-diff
  • API Reference
  • Pre-Trends Power Analysis
  • View page source

Pre-Trends Power Analysis

Power analysis for pre-trends tests (Roth 2022).

Overview

Passing a pre-trends test does not guarantee that parallel trends holds. Roth (2022) shows that pre-trends tests are often underpowered to detect economically meaningful violations of parallel trends. This module provides tools to assess:

  1. Power: The probability of rejecting the null (no pre-trends) given a violation

  2. Minimum Detectable Violation (MDV): The smallest violation detectable at target power

Key insights from Roth (2022):

  • Pre-trends tests are joint tests that pre-period coefficients equal zero

  • Standard pre-trends tests often have low power against linear trends

  • A “passed” pre-trends test may simply reflect lack of statistical power

  • MDV provides the minimum violation the test could have detected

PreTrendsPower

Main class for pre-trends power analysis.

class diff_diff.PreTrendsPower[source]

Bases: object

Pre-trends power analysis (Roth 2022).

Computes the power of pre-trends tests to detect violations of parallel trends, and the minimum detectable violation (MDV).

Parameters:
  • alpha (float, default=0.05) – Significance level for the pre-trends test.

  • power (float, default=0.80) – Target power level for MDV calculation.

  • violation_type (str, default='linear') – Type of violation pattern to consider: - ‘linear’: Violations follow a linear trend (most common) - ‘constant’: Same violation in all pre-periods - ‘last_period’: Violation only in the last pre-period - ‘custom’: User-specified violation pattern (via violation_weights)

  • violation_weights (array-like, optional) – Custom weights for violation pattern. Length must equal number of pre-periods. Only used when violation_type=’custom’.

Examples

Basic usage with MultiPeriodDiD results:

>>> from diff_diff import MultiPeriodDiD
>>> from diff_diff.pretrends import PreTrendsPower
>>>
>>> # Fit event study
>>> mp_did = MultiPeriodDiD()
>>> results = mp_did.fit(data, outcome='y', treatment='treated',
...                      time='period', post_periods=[4, 5, 6, 7])
>>>
>>> # Analyze pre-trends power
>>> pt = PreTrendsPower(alpha=0.05, power=0.80)
>>> power_results = pt.fit(results)
>>> print(power_results.summary())
>>>
>>> # Get power curve
>>> curve = pt.power_curve(results)
>>> curve.plot()

Notes

The pre-trends test is typically a joint test that all pre-period coefficients are zero. This test has limited power to detect small violations, especially when:

  1. There are few pre-periods

  2. Standard errors are large

  3. The violation pattern is smooth (e.g., linear trend)

Passing a pre-trends test does NOT mean parallel trends holds. It means violations smaller than the MDV cannot be ruled out. For robust inference, combine with HonestDiD sensitivity analysis.

References

Roth, J. (2022). Pretest with Caution: Event-Study Estimates after Testing

for Parallel Trends. American Economic Review: Insights, 4(3), 305-322.

Methods

fit(results[, M, pre_periods])

Compute pre-trends power analysis.

power_curve(results[, M_grid, n_points, ...])

Compute power across a range of violation magnitudes.

sensitivity_to_honest_did(results[, pre_periods])

Compare pre-trends power analysis with HonestDiD sensitivity.

__init__(alpha=0.05, power=0.8, violation_type='linear', violation_weights=None)[source]
Parameters:
  • alpha (float)

  • power (float)

  • violation_type (Literal['linear', 'constant', 'last_period', 'custom'])

  • violation_weights (ndarray | None)

get_params()[source]

Get parameters for this estimator.

Return type:

Dict[str, Any]

set_params(**params)[source]

Set parameters for this estimator.

Return type:

PreTrendsPower

fit(results, M=None, pre_periods=None)[source]

Compute pre-trends power analysis.

Parameters:
  • results (MultiPeriodDiDResults, CallawaySantAnnaResults, or SunAbrahamResults) – Results from an event study estimation.

  • M (float, optional) – Specific violation magnitude to evaluate. If None, evaluates at a default magnitude based on the data.

  • pre_periods (list of int, optional) – Explicit list of pre-treatment periods to use for power analysis. If None, attempts to infer from results.pre_periods. Use this when you’ve estimated an event study with all periods in post_periods and need to specify which are actually pre-treatment.

Returns:

Power analysis results including power and MDV.

Return type:

PreTrendsPowerResults

power_at(results, M, pre_periods=None)[source]

Compute power to detect a specific violation magnitude.

Parameters:
  • results (results object) – Event study results.

  • M (float) – Violation magnitude.

  • pre_periods (list of int, optional) – Explicit list of pre-treatment periods. See fit() for details.

Returns:

Power to detect violation of magnitude M.

Return type:

float

power_curve(results, M_grid=None, n_points=50, pre_periods=None)[source]

Compute power across a range of violation magnitudes.

Parameters:
  • results (results object) – Event study results.

  • M_grid (list of float, optional) – Specific violation magnitudes to evaluate. If None, creates automatic grid from 0 to 2.5 * MDV.

  • n_points (int, default=50) – Number of points in automatic grid.

  • pre_periods (list of int, optional) – Explicit list of pre-treatment periods. See fit() for details.

Returns:

Power curve data with plot method.

Return type:

PreTrendsPowerCurve

sensitivity_to_honest_did(results, pre_periods=None)[source]

Compare pre-trends power analysis with HonestDiD sensitivity.

This method helps interpret how informative a passing pre-trends test is in the context of HonestDiD’s relative magnitudes restriction.

Parameters:
  • results (results object) – Event study results.

  • pre_periods (list of int, optional) – Explicit list of pre-treatment periods. See fit() for details.

Returns:

Dictionary with: - mdv: Minimum detectable violation from pre-trends test - honest_M_at_mdv: Corresponding M value for HonestDiD - interpretation: Text explaining the relationship

Return type:

dict

Example

from diff_diff import MultiPeriodDiD, PreTrendsPower

# First fit an event study
model = MultiPeriodDiD(reference_period=-1)
results = model.fit(data, outcome='y', treated='treated',
                    time='period', unit='unit_id', treatment_start=5)

# Compute pre-trends power for linear violations
pt = PreTrendsPower(alpha=0.05, power=0.80, violation_type='linear')
pt_results = pt.fit(results)

print(f"MDV: {pt_results.mdv:.3f}")
print(f"Power: {pt_results.power:.2%}")

PreTrendsPowerResults

Results from pre-trends power analysis.

class diff_diff.PreTrendsPowerResults[source]

Bases: object

Results from pre-trends power analysis.

power

Power to detect the specified violation pattern at given alpha.

Type:

float

mdv

Minimum detectable violation (smallest M detectable at target power).

Type:

float

violation_magnitude

The magnitude of violation tested (M parameter).

Type:

float

violation_type

Type of violation pattern (‘linear’, ‘constant’, ‘last_period’, ‘custom’).

Type:

str

alpha

Significance level for the pre-trends test.

Type:

float

target_power

Target power level used for MDV calculation.

Type:

float

n_pre_periods

Number of pre-treatment periods in the event study.

Type:

int

test_statistic

Expected test statistic under the specified violation.

Type:

float

critical_value

Critical value for the pre-trends test.

Type:

float

noncentrality

Non-centrality parameter under the alternative hypothesis.

Type:

float

pre_period_effects

Estimated pre-period effects from the event study.

Type:

np.ndarray

pre_period_ses

Standard errors of pre-period effects.

Type:

np.ndarray

vcov

Variance-covariance matrix of pre-period effects.

Type:

np.ndarray

power: float
mdv: float
violation_magnitude: float
violation_type: str
alpha: float
target_power: float
n_pre_periods: int
test_statistic: float
critical_value: float
noncentrality: float
pre_period_effects: ndarray
pre_period_ses: ndarray
vcov: ndarray
original_results: Any | None = None
property is_informative: bool

Check if the pre-trends test is informative.

A pre-trends test is considered informative if the MDV is reasonably small relative to typical effect sizes. This is a heuristic check; see the summary for interpretation guidance.

property power_adequate: bool

Check if power meets the target threshold.

summary()[source]

Generate formatted summary of pre-trends power analysis.

Returns:

Formatted summary.

Return type:

str

print_summary()[source]

Print summary to stdout.

Return type:

None

to_dict()[source]

Convert results to dictionary.

Return type:

Dict[str, Any]

to_dataframe()[source]

Convert results to DataFrame.

Return type:

DataFrame

power_at(M)[source]

Compute power to detect a specific violation magnitude.

This method allows computing power at different M values without re-fitting the model, using the stored variance-covariance matrix.

Parameters:

M (float) – Violation magnitude to evaluate.

Returns:

Power to detect violation of magnitude M.

Return type:

float

__init__(power, mdv, violation_magnitude, violation_type, alpha, target_power, n_pre_periods, test_statistic, critical_value, noncentrality, pre_period_effects, pre_period_ses, vcov, original_results=None)
Parameters:
  • power (float)

  • mdv (float)

  • violation_magnitude (float)

  • violation_type (str)

  • alpha (float)

  • target_power (float)

  • n_pre_periods (int)

  • test_statistic (float)

  • critical_value (float)

  • noncentrality (float)

  • pre_period_effects (ndarray)

  • pre_period_ses (ndarray)

  • vcov (ndarray)

  • original_results (Any | None)

Return type:

None

PreTrendsPowerCurve

Power curve across violation magnitudes.

class diff_diff.PreTrendsPowerCurve[source]

Bases: object

Power curve across violation magnitudes.

M_values

Grid of violation magnitudes tested.

Type:

np.ndarray

powers

Power at each violation magnitude.

Type:

np.ndarray

mdv

Minimum detectable violation.

Type:

float

alpha

Significance level.

Type:

float

target_power

Target power level.

Type:

float

violation_type

Type of violation pattern.

Type:

str

M_values: ndarray
powers: ndarray
mdv: float
alpha: float
target_power: float
violation_type: str
to_dataframe()[source]

Convert to DataFrame with M and power columns.

Return type:

DataFrame

plot(ax=None, show_mdv=True, show_target=True, color='#2563eb', mdv_color='#dc2626', target_color='#22c55e', **kwargs)[source]

Plot the power curve.

Parameters:
  • ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, creates new figure.

  • show_mdv (bool, default=True) – Whether to show vertical line at MDV.

  • show_target (bool, default=True) – Whether to show horizontal line at target power.

  • color (str) – Color for power curve line.

  • mdv_color (str) – Color for MDV vertical line.

  • target_color (str) – Color for target power horizontal line.

  • **kwargs – Additional arguments passed to plt.plot().

Returns:

ax – The axes with the plot.

Return type:

matplotlib.axes.Axes

__init__(M_values, powers, mdv, alpha, target_power, violation_type)
Parameters:
  • M_values (ndarray)

  • powers (ndarray)

  • mdv (float)

  • alpha (float)

  • target_power (float)

  • violation_type (str)

Return type:

None

Convenience Functions

compute_pretrends_power

Quick computation of pre-trends power.

diff_diff.compute_pretrends_power(results, M=None, alpha=0.05, target_power=0.8, violation_type='linear', pre_periods=None)[source]

Convenience function for pre-trends power analysis.

Parameters:
  • results (results object) – Event study results.

  • M (float, optional) – Violation magnitude to evaluate.

  • alpha (float, default=0.05) – Significance level.

  • target_power (float, default=0.80) – Target power for MDV calculation.

  • violation_type (str, default='linear') – Type of violation pattern.

  • pre_periods (list of int, optional) – Explicit list of pre-treatment periods. If None, attempts to infer from results. Use when you’ve estimated all periods as post_periods.

Returns:

Power analysis results.

Return type:

PreTrendsPowerResults

Examples

>>> from diff_diff import MultiPeriodDiD
>>> from diff_diff.pretrends import compute_pretrends_power
>>>
>>> results = MultiPeriodDiD().fit(data, ...)
>>> power_results = compute_pretrends_power(results, pre_periods=[0, 1, 2, 3])
>>> print(f"MDV: {power_results.mdv:.3f}")
>>> print(f"Power: {power_results.power:.1%}")

compute_mdv

Compute minimum detectable violation.

diff_diff.compute_mdv(results, alpha=0.05, target_power=0.8, violation_type='linear', pre_periods=None)[source]

Compute minimum detectable violation.

Parameters:
  • results (results object) – Event study results.

  • alpha (float, default=0.05) – Significance level.

  • target_power (float, default=0.80) – Target power for MDV calculation.

  • violation_type (str, default='linear') – Type of violation pattern.

  • pre_periods (list of int, optional) – Explicit list of pre-treatment periods. If None, attempts to infer from results. Use when you’ve estimated all periods as post_periods.

Returns:

Minimum detectable violation.

Return type:

float

Violation Types

The module supports several types of pre-trends violations:

linear

Linear trend violations where each pre-period differs from the reference by an amount proportional to distance. delta[t] = M * t for pre-periods.

constant

Constant violations where all pre-periods have the same deviation. delta[t] = M for all pre-periods.

last_period

Only the period immediately before treatment is violated. delta[-1] = M, all other pre-periods are zero.

custom

User-specified violation pattern via the custom_delta parameter.

Complete Example

import numpy as np
from diff_diff import (
    MultiPeriodDiD,
    PreTrendsPower,
    compute_mdv,
    plot_pretrends_power,
)

# Fit event study
model = MultiPeriodDiD(reference_period=-1)
results = model.fit(data, outcome='y', treated='treated',
                    time='period', unit='unit_id', treatment_start=5)

# Compute MDV
mdv = compute_mdv(results, alpha=0.05, power=0.80)
print(f"Minimum Detectable Violation: {mdv:.3f}")

# Power curve analysis
pt = PreTrendsPower(alpha=0.05, violation_type='linear')
curve = pt.power_curve(results, n_points=50)

# Plot power curve
fig = plot_pretrends_power(curve, show_mdv=True, target_power=0.80)
fig.savefig('pretrends_power.png')

# Integration with HonestDiD
sensitivity = pt.sensitivity_to_honest_did(
    results,
    honest_method='smoothness',
    M_grid=np.linspace(0, mdv, 21)
)

References

  • Roth, J. (2022). Pretest with Caution: Event-Study Estimates after Testing for Parallel Trends. American Economic Review: Insights, 4(3), 305-322.

  • R package: pretrends

See Also

  • Honest DiD - Sensitivity analysis under parallel trends violations

  • Utilities - Standard parallel trends tests

Previous Next

© Copyright 2026, diff-diff contributors.

Built with Sphinx using a theme provided by Read the Docs.