diff --git a/.github/workflows/docs-tests.yml b/.github/workflows/docs-tests.yml index 53922823e..1f1b09e6c 100644 --- a/.github/workflows/docs-tests.yml +++ b/.github/workflows/docs-tests.yml @@ -118,7 +118,7 @@ jobs: # docs/conf.py imports diff_diff via sys.path from checked-out source. # ipython provides the 'ipython3' Pygments lexer that nbsphinx uses # for notebook code cells; without it -W fires highlighting_failure. - run: pip install "numpy>=1.20.0" "pandas>=1.3.0" "scipy>=1.10" "sphinx>=6.0" "pydata-sphinx-theme>=0.16.1" "sphinxext-opengraph>=0.9" "sphinx-sitemap>=2.5" "nbsphinx>=0.9" "myst-parser>=2.0" "matplotlib>=3.5" "ipython>=8.0" + run: pip install "numpy>=1.20.0" "pandas>=1.3.0" "scipy>=1.10" "sphinx>=6.0" "pydata-sphinx-theme>=0.16.1" "sphinxext-opengraph>=0.9" "sphinx-sitemap>=2.5" "nbsphinx>=0.9" "myst-parser>=2.0" "sphinx-design>=0.6.1" "matplotlib>=3.5" "ipython>=8.0" - name: Build docs with warnings as errors # SPHINXOPTS="-W" turns every Sphinx warning into a build failure. @@ -154,7 +154,7 @@ jobs: # not run a Sphinx build (sphinx-build covers full rendering on 3.11). # Failure here means the docs floor declared in pyproject.toml / # .readthedocs.yaml / above is not installable on Python 3.9. - run: pip install "numpy>=1.20.0" "pandas>=1.3.0" "scipy>=1.10" "sphinx>=6.0" "pydata-sphinx-theme>=0.16.1" "sphinxext-opengraph>=0.9" "sphinx-sitemap>=2.5" "nbsphinx>=0.9" "myst-parser>=2.0" "matplotlib>=3.5" "ipython>=8.0" + run: pip install "numpy>=1.20.0" "pandas>=1.3.0" "scipy>=1.10" "sphinx>=6.0" "pydata-sphinx-theme>=0.16.1" "sphinxext-opengraph>=0.9" "sphinx-sitemap>=2.5" "nbsphinx>=0.9" "myst-parser>=2.0" "sphinx-design>=0.6.1" "matplotlib>=3.5" "ipython>=8.0" - name: Confirm pydata-sphinx-theme version # Surface the resolved version in the log for future debugging. diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f61cd9c8b..c443dc57b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -18,7 +18,7 @@ build: # # Keep in sync with pyproject.toml [project.dependencies] # and [project.optional-dependencies.docs]. - - pip install "numpy>=1.20.0" "pandas>=1.3.0" "scipy>=1.10" "sphinx>=6.0" "pydata-sphinx-theme>=0.16.1" "sphinxext-opengraph>=0.9" "sphinx-sitemap>=2.5" "nbsphinx>=0.9" "myst-parser>=2.0" "matplotlib>=3.5" "ipython>=8.0" + - pip install "numpy>=1.20.0" "pandas>=1.3.0" "scipy>=1.10" "sphinx>=6.0" "pydata-sphinx-theme>=0.16.1" "sphinxext-opengraph>=0.9" "sphinx-sitemap>=2.5" "nbsphinx>=0.9" "myst-parser>=2.0" "sphinx-design>=0.6.1" "matplotlib>=3.5" "ipython>=8.0" # Build documentation in the "docs/" directory with Sphinx sphinx: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5504fb080..ccbb5bc8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Changed +- **Documentation site restructured around 5 top-level sections** (Getting Started / + Practitioner Guide / Tutorials / User Guide / API Reference). The previous flat + navigation put 40 pages into the pydata-sphinx-theme header, leaving most of the + site (including the API reference) reachable only through an oversized "More" + dropdown; the navbar now shows exactly the 5 sections, each with a card-grid + landing page (new `sphinx-design` docs dependency). Tutorials get a grouped index + at `tutorials/index.html` with short sidebar labels, and tutorial pages now show + their sibling notebooks in the left sidebar. All existing page URLs are unchanged. - **Internal: dev tooling pins bumped** (Dependabot group + manual lint.yml sync): `black==26.5.1`, `ruff==0.15.21`, `mypy==2.3.0` in both the `dev` extra and the Lint CI workflow. mypy >= 2.2 can no longer target Python 3.9, so diff --git a/CLAUDE.md b/CLAUDE.md index d187bb776..ab469b54b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -149,7 +149,10 @@ When adding new functionality, the source of truth is: - **`diff_diff/guides/llms.txt`** for the AI-agent contract (one-line catalog entry per estimator with paper citation + RTD link). This file is bundled in the wheel and published on RTD via `docs/conf.py` `html_extra_path`. - **`docs/api/*.rst`** for full API reference. - **`docs/references.rst`** for scholarly citations. -- **`docs/tutorials/*.ipynb`** for hands-on examples. +- **`docs/tutorials/*.ipynb`** for hands-on examples. New notebooks are registered in + `docs/tutorials/index.rst` (toctree entry with a short display label + a card in the + matching group), NOT in `docs/index.rst` - the root toctree lists only the 5 section + landing pages so the navbar stays at 5 links. - **`CHANGELOG.md`** for release notes. - **`README.md`** for ONE LINE in the `## Estimators` flat catalog (or `## Diagnostics & Sensitivity` for diagnostic-class features). Do NOT add usage examples, parameter tables, per-estimator sections, or full bibliographies. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb613c83a..a86c19ce2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,6 +61,10 @@ If you find yourself adding a usage example, a parameter table, or a multi-parag 3. **`docs/tutorials/*.ipynb`** - Update relevant tutorial or create new one: - Working code examples - Explanation of when/why to use the feature + - New notebooks are registered in `docs/tutorials/index.rst` (NOT `docs/index.rst`): + add a toctree entry with a short display label to the matching group + (Business Applications / Fundamentals / Advanced Methods / Study Design) + plus a `grid-item-card` in that group's card grid 4. **`docs/references.rst`** (bibliography source of truth) - Add: - Full citation under the appropriate sub-section (matches the `### Subsection` headings already in that file) diff --git a/docs/api/_autosummary/diff_diff.BaconDecompositionResults.rst b/docs/api/_autosummary/diff_diff.BaconDecompositionResults.rst index 222a72a0e..a4afa3cde 100644 --- a/docs/api/_autosummary/diff_diff.BaconDecompositionResults.rst +++ b/docs/api/_autosummary/diff_diff.BaconDecompositionResults.rst @@ -26,6 +26,7 @@ .. autosummary:: ~BaconDecompositionResults.decomposition_error + ~BaconDecompositionResults.n_always_treated_remapped ~BaconDecompositionResults.n_obs ~BaconDecompositionResults.survey_metadata ~BaconDecompositionResults.twfe_estimate diff --git a/docs/api/_autosummary/diff_diff.CSBootstrapResults.rst b/docs/api/_autosummary/diff_diff.CSBootstrapResults.rst index 60b3ca1a1..01cbfe5b5 100644 --- a/docs/api/_autosummary/diff_diff.CSBootstrapResults.rst +++ b/docs/api/_autosummary/diff_diff.CSBootstrapResults.rst @@ -28,15 +28,15 @@ ~CSBootstrapResults.group_effect_cis ~CSBootstrapResults.group_effect_p_values ~CSBootstrapResults.group_effect_ses + ~CSBootstrapResults.overall_att_es_ci + ~CSBootstrapResults.overall_att_es_p_value + ~CSBootstrapResults.overall_att_es_se ~CSBootstrapResults.n_bootstrap ~CSBootstrapResults.weight_type ~CSBootstrapResults.alpha ~CSBootstrapResults.overall_att_se ~CSBootstrapResults.overall_att_ci ~CSBootstrapResults.overall_att_p_value - ~CSBootstrapResults.overall_att_es_se - ~CSBootstrapResults.overall_att_es_ci - ~CSBootstrapResults.overall_att_es_p_value ~CSBootstrapResults.group_time_ses ~CSBootstrapResults.group_time_cis ~CSBootstrapResults.group_time_p_values diff --git a/docs/api/_autosummary/diff_diff.CallawaySantAnnaResults.rst b/docs/api/_autosummary/diff_diff.CallawaySantAnnaResults.rst index e264159fe..12aaa22d7 100644 --- a/docs/api/_autosummary/diff_diff.CallawaySantAnnaResults.rst +++ b/docs/api/_autosummary/diff_diff.CallawaySantAnnaResults.rst @@ -24,15 +24,18 @@ .. autosummary:: + ~CallawaySantAnnaResults.allow_unbalanced_panel ~CallawaySantAnnaResults.alpha ~CallawaySantAnnaResults.anticipation ~CallawaySantAnnaResults.att ~CallawaySantAnnaResults.base_period ~CallawaySantAnnaResults.bootstrap_results ~CallawaySantAnnaResults.cband_crit_value + ~CallawaySantAnnaResults.cluster_name ~CallawaySantAnnaResults.coef_var ~CallawaySantAnnaResults.conf_int ~CallawaySantAnnaResults.control_group + ~CallawaySantAnnaResults.df_inference ~CallawaySantAnnaResults.epv_diagnostics ~CallawaySantAnnaResults.epv_threshold ~CallawaySantAnnaResults.event_study_effects @@ -41,6 +44,7 @@ ~CallawaySantAnnaResults.group_effects ~CallawaySantAnnaResults.influence_functions ~CallawaySantAnnaResults.is_significant + ~CallawaySantAnnaResults.n_clusters ~CallawaySantAnnaResults.p_value ~CallawaySantAnnaResults.panel ~CallawaySantAnnaResults.pscore_fallback @@ -49,6 +53,8 @@ ~CallawaySantAnnaResults.significance_stars ~CallawaySantAnnaResults.survey_metadata ~CallawaySantAnnaResults.t_stat + ~CallawaySantAnnaResults.used_rc_on_unbalanced_panel + ~CallawaySantAnnaResults.vcov_type ~CallawaySantAnnaResults.group_time_effects ~CallawaySantAnnaResults.overall_att ~CallawaySantAnnaResults.overall_se diff --git a/docs/api/_autosummary/diff_diff.ChangesInChanges.rst b/docs/api/_autosummary/diff_diff.ChangesInChanges.rst new file mode 100644 index 000000000..cf5bb65fa --- /dev/null +++ b/docs/api/_autosummary/diff_diff.ChangesInChanges.rst @@ -0,0 +1,21 @@ +diff\_diff.ChangesInChanges +=========================== + +.. currentmodule:: diff_diff + +.. autoclass:: ChangesInChanges + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~ChangesInChanges.__init__ + ~ChangesInChanges.fit + ~ChangesInChanges.get_params + ~ChangesInChanges.set_params + + + + diff --git a/docs/api/_autosummary/diff_diff.ContinuousDiDResults.rst b/docs/api/_autosummary/diff_diff.ContinuousDiDResults.rst index 282e92551..2d4609550 100644 --- a/docs/api/_autosummary/diff_diff.ContinuousDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.ContinuousDiDResults.rst @@ -31,7 +31,10 @@ ~ContinuousDiDResults.coef_var ~ContinuousDiDResults.conf_int ~ContinuousDiDResults.control_group + ~ContinuousDiDResults.covariates ~ContinuousDiDResults.degree + ~ContinuousDiDResults.epv_threshold + ~ContinuousDiDResults.estimation_method ~ContinuousDiDResults.event_study_effects ~ContinuousDiDResults.is_significant ~ContinuousDiDResults.n_bootstrap @@ -41,12 +44,16 @@ ~ContinuousDiDResults.overall_se ~ContinuousDiDResults.overall_t_stat ~ContinuousDiDResults.p_value + ~ContinuousDiDResults.pscore_fallback + ~ContinuousDiDResults.pscore_trim ~ContinuousDiDResults.rank_deficient_action + ~ContinuousDiDResults.reference_dose ~ContinuousDiDResults.se ~ContinuousDiDResults.seed ~ContinuousDiDResults.significance_stars ~ContinuousDiDResults.survey_metadata ~ContinuousDiDResults.t_stat + ~ContinuousDiDResults.treatment_type ~ContinuousDiDResults.dose_response_att ~ContinuousDiDResults.dose_response_acrt ~ContinuousDiDResults.overall_att diff --git a/docs/api/_autosummary/diff_diff.DiDResults.rst b/docs/api/_autosummary/diff_diff.DiDResults.rst index 0d95b3941..be93d9f2d 100644 --- a/docs/api/_autosummary/diff_diff.DiDResults.rst +++ b/docs/api/_autosummary/diff_diff.DiDResults.rst @@ -30,11 +30,14 @@ ~DiDResults.coef_var ~DiDResults.coefficients ~DiDResults.conley_lag_cutoff + ~DiDResults.df_convention ~DiDResults.fitted_values + ~DiDResults.inference_df ~DiDResults.inference_method ~DiDResults.is_significant ~DiDResults.n_bootstrap ~DiDResults.n_clusters + ~DiDResults.p_val_type ~DiDResults.r_squared ~DiDResults.residuals ~DiDResults.significance_stars diff --git a/docs/api/_autosummary/diff_diff.EfficientDiDResults.rst b/docs/api/_autosummary/diff_diff.EfficientDiDResults.rst index 193419cd4..8ff6ce9ab 100644 --- a/docs/api/_autosummary/diff_diff.EfficientDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.EfficientDiDResults.rst @@ -43,6 +43,7 @@ ~EfficientDiDResults.n_bootstrap ~EfficientDiDResults.n_clusters ~EfficientDiDResults.omega_condition_numbers + ~EfficientDiDResults.omega_ridge ~EfficientDiDResults.p_value ~EfficientDiDResults.pt_assumption ~EfficientDiDResults.ratio_clip diff --git a/docs/api/_autosummary/diff_diff.GroupTimeEffect.rst b/docs/api/_autosummary/diff_diff.GroupTimeEffect.rst index 3f3748730..458d7bdc9 100644 --- a/docs/api/_autosummary/diff_diff.GroupTimeEffect.rst +++ b/docs/api/_autosummary/diff_diff.GroupTimeEffect.rst @@ -22,6 +22,7 @@ ~GroupTimeEffect.is_significant ~GroupTimeEffect.significance_stars + ~GroupTimeEffect.skip_reason ~GroupTimeEffect.group ~GroupTimeEffect.time ~GroupTimeEffect.effect diff --git a/docs/api/_autosummary/diff_diff.ImputationDiDResults.rst b/docs/api/_autosummary/diff_diff.ImputationDiDResults.rst index 367e35aaa..f2cf18a17 100644 --- a/docs/api/_autosummary/diff_diff.ImputationDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.ImputationDiDResults.rst @@ -16,6 +16,7 @@ ~ImputationDiDResults.print_summary ~ImputationDiDResults.summary ~ImputationDiDResults.to_dataframe + ~ImputationDiDResults.to_dict @@ -28,15 +29,19 @@ ~ImputationDiDResults.anticipation ~ImputationDiDResults.att ~ImputationDiDResults.bootstrap_results + ~ImputationDiDResults.cluster_name ~ImputationDiDResults.coef_var ~ImputationDiDResults.conf_int ~ImputationDiDResults.is_significant + ~ImputationDiDResults.leave_one_out + ~ImputationDiDResults.n_clusters ~ImputationDiDResults.p_value ~ImputationDiDResults.pretrend_results ~ImputationDiDResults.se ~ImputationDiDResults.significance_stars ~ImputationDiDResults.survey_metadata ~ImputationDiDResults.t_stat + ~ImputationDiDResults.vcov_type ~ImputationDiDResults.treatment_effects ~ImputationDiDResults.overall_att ~ImputationDiDResults.overall_se diff --git a/docs/api/_autosummary/diff_diff.MultiPeriodDiDResults.rst b/docs/api/_autosummary/diff_diff.MultiPeriodDiDResults.rst index 7f7dd2153..058bafd63 100644 --- a/docs/api/_autosummary/diff_diff.MultiPeriodDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.MultiPeriodDiDResults.rst @@ -32,7 +32,9 @@ ~MultiPeriodDiDResults.coefficients ~MultiPeriodDiDResults.conf_int ~MultiPeriodDiDResults.conley_lag_cutoff + ~MultiPeriodDiDResults.df_convention ~MultiPeriodDiDResults.fitted_values + ~MultiPeriodDiDResults.inference_df ~MultiPeriodDiDResults.inference_method ~MultiPeriodDiDResults.interaction_indices ~MultiPeriodDiDResults.is_significant diff --git a/docs/api/_autosummary/diff_diff.PreTrendsPowerCurve.rst b/docs/api/_autosummary/diff_diff.PreTrendsPowerCurve.rst index aa6795329..ed681361e 100644 --- a/docs/api/_autosummary/diff_diff.PreTrendsPowerCurve.rst +++ b/docs/api/_autosummary/diff_diff.PreTrendsPowerCurve.rst @@ -22,11 +22,11 @@ .. autosummary:: + ~PreTrendsPowerCurve.pretest_form ~PreTrendsPowerCurve.M_values ~PreTrendsPowerCurve.powers ~PreTrendsPowerCurve.mdv ~PreTrendsPowerCurve.alpha ~PreTrendsPowerCurve.target_power ~PreTrendsPowerCurve.violation_type - ~PreTrendsPowerCurve.pretest_form diff --git a/docs/api/_autosummary/diff_diff.PreTrendsPowerResults.rst b/docs/api/_autosummary/diff_diff.PreTrendsPowerResults.rst index 247da6e68..a1df642a4 100644 --- a/docs/api/_autosummary/diff_diff.PreTrendsPowerResults.rst +++ b/docs/api/_autosummary/diff_diff.PreTrendsPowerResults.rst @@ -25,10 +25,14 @@ .. autosummary:: + ~PreTrendsPowerResults.covariance_source ~PreTrendsPowerResults.is_informative ~PreTrendsPowerResults.max_abs_pre_violation + ~PreTrendsPowerResults.nis_box_probability ~PreTrendsPowerResults.original_results ~PreTrendsPowerResults.power_adequate + ~PreTrendsPowerResults.pretest_form + ~PreTrendsPowerResults.violation_weights ~PreTrendsPowerResults.power ~PreTrendsPowerResults.mdv ~PreTrendsPowerResults.violation_magnitude @@ -42,8 +46,4 @@ ~PreTrendsPowerResults.pre_period_effects ~PreTrendsPowerResults.pre_period_ses ~PreTrendsPowerResults.vcov - ~PreTrendsPowerResults.pretest_form - ~PreTrendsPowerResults.nis_box_probability - ~PreTrendsPowerResults.violation_weights - ~PreTrendsPowerResults.covariance_source diff --git a/docs/api/_autosummary/diff_diff.QDiD.rst b/docs/api/_autosummary/diff_diff.QDiD.rst new file mode 100644 index 000000000..b28a178df --- /dev/null +++ b/docs/api/_autosummary/diff_diff.QDiD.rst @@ -0,0 +1,21 @@ +diff\_diff.QDiD +=============== + +.. currentmodule:: diff_diff + +.. autoclass:: QDiD + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~QDiD.__init__ + ~QDiD.fit + ~QDiD.get_params + ~QDiD.set_params + + + + diff --git a/docs/api/_autosummary/diff_diff.RDPlot.rst b/docs/api/_autosummary/diff_diff.RDPlot.rst new file mode 100644 index 000000000..4ae0b0633 --- /dev/null +++ b/docs/api/_autosummary/diff_diff.RDPlot.rst @@ -0,0 +1,21 @@ +diff\_diff.RDPlot +================= + +.. currentmodule:: diff_diff + +.. autoclass:: RDPlot + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~RDPlot.__init__ + ~RDPlot.fit + ~RDPlot.get_params + ~RDPlot.set_params + + + + diff --git a/docs/api/_autosummary/diff_diff.RDPlotResult.rst b/docs/api/_autosummary/diff_diff.RDPlotResult.rst new file mode 100644 index 000000000..6d62b8aee --- /dev/null +++ b/docs/api/_autosummary/diff_diff.RDPlotResult.rst @@ -0,0 +1,49 @@ +diff\_diff.RDPlotResult +======================= + +.. currentmodule:: diff_diff + +.. autoclass:: RDPlotResult + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~RDPlotResult.__init__ + ~RDPlotResult.plot + ~RDPlotResult.summary + ~RDPlotResult.to_dataframe + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~RDPlotResult.covariate_coefficients + ~RDPlotResult.covariates_dropped + ~RDPlotResult.wimse_bias_weight + ~RDPlotResult.wimse_variance_weight + ~RDPlotResult.coef + ~RDPlotResult.vars_bins + ~RDPlotResult.vars_poly + ~RDPlotResult.J + ~RDPlotResult.J_IMSE + ~RDPlotResult.J_MV + ~RDPlotResult.scale + ~RDPlotResult.rscale + ~RDPlotResult.bin_avg + ~RDPlotResult.bin_med + ~RDPlotResult.p + ~RDPlotResult.cutoff + ~RDPlotResult.h + ~RDPlotResult.N + ~RDPlotResult.N_h + ~RDPlotResult.binselect + ~RDPlotResult.kernel_type + ~RDPlotResult.ci_level + ~RDPlotResult.ci_requested + diff --git a/docs/api/_autosummary/diff_diff.RegressionDiscontinuity.rst b/docs/api/_autosummary/diff_diff.RegressionDiscontinuity.rst new file mode 100644 index 000000000..841956cf4 --- /dev/null +++ b/docs/api/_autosummary/diff_diff.RegressionDiscontinuity.rst @@ -0,0 +1,21 @@ +diff\_diff.RegressionDiscontinuity +================================== + +.. currentmodule:: diff_diff + +.. autoclass:: RegressionDiscontinuity + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~RegressionDiscontinuity.__init__ + ~RegressionDiscontinuity.fit + ~RegressionDiscontinuity.get_params + ~RegressionDiscontinuity.set_params + + + + diff --git a/docs/api/_autosummary/diff_diff.RegressionDiscontinuityResults.rst b/docs/api/_autosummary/diff_diff.RegressionDiscontinuityResults.rst new file mode 100644 index 000000000..1ab0c6144 --- /dev/null +++ b/docs/api/_autosummary/diff_diff.RegressionDiscontinuityResults.rst @@ -0,0 +1,95 @@ +diff\_diff.RegressionDiscontinuityResults +========================================= + +.. currentmodule:: diff_diff + +.. autoclass:: RegressionDiscontinuityResults + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~RegressionDiscontinuityResults.__init__ + ~RegressionDiscontinuityResults.print_summary + ~RegressionDiscontinuityResults.summary + ~RegressionDiscontinuityResults.to_dataframe + ~RegressionDiscontinuityResults.to_dict + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~RegressionDiscontinuityResults.beta_p_left + ~RegressionDiscontinuityResults.beta_p_right + ~RegressionDiscontinuityResults.beta_t_p_left + ~RegressionDiscontinuityResults.beta_t_p_right + ~RegressionDiscontinuityResults.covariate_coefficients + ~RegressionDiscontinuityResults.covariates + ~RegressionDiscontinuityResults.covariates_dropped + ~RegressionDiscontinuityResults.first_stage + ~RegressionDiscontinuityResults.first_stage_conf_int + ~RegressionDiscontinuityResults.first_stage_conf_int_bias_corrected + ~RegressionDiscontinuityResults.first_stage_conf_int_conventional + ~RegressionDiscontinuityResults.first_stage_conventional + ~RegressionDiscontinuityResults.first_stage_covariate_coefficients + ~RegressionDiscontinuityResults.first_stage_p_value + ~RegressionDiscontinuityResults.first_stage_p_value_bias_corrected + ~RegressionDiscontinuityResults.first_stage_p_value_conventional + ~RegressionDiscontinuityResults.first_stage_se + ~RegressionDiscontinuityResults.first_stage_se_conventional + ~RegressionDiscontinuityResults.first_stage_t_stat + ~RegressionDiscontinuityResults.first_stage_t_stat_bias_corrected + ~RegressionDiscontinuityResults.first_stage_t_stat_conventional + ~RegressionDiscontinuityResults.att + ~RegressionDiscontinuityResults.se + ~RegressionDiscontinuityResults.t_stat + ~RegressionDiscontinuityResults.p_value + ~RegressionDiscontinuityResults.conf_int + ~RegressionDiscontinuityResults.alpha + ~RegressionDiscontinuityResults.att_conventional + ~RegressionDiscontinuityResults.se_conventional + ~RegressionDiscontinuityResults.t_stat_conventional + ~RegressionDiscontinuityResults.p_value_conventional + ~RegressionDiscontinuityResults.conf_int_conventional + ~RegressionDiscontinuityResults.t_stat_bias_corrected + ~RegressionDiscontinuityResults.p_value_bias_corrected + ~RegressionDiscontinuityResults.conf_int_bias_corrected + ~RegressionDiscontinuityResults.se_robust + ~RegressionDiscontinuityResults.h_left + ~RegressionDiscontinuityResults.h_right + ~RegressionDiscontinuityResults.b_left + ~RegressionDiscontinuityResults.b_right + ~RegressionDiscontinuityResults.n_obs + ~RegressionDiscontinuityResults.n_left + ~RegressionDiscontinuityResults.n_right + ~RegressionDiscontinuityResults.n_h_left + ~RegressionDiscontinuityResults.n_h_right + ~RegressionDiscontinuityResults.n_b_left + ~RegressionDiscontinuityResults.n_b_right + ~RegressionDiscontinuityResults.n_unique_left + ~RegressionDiscontinuityResults.n_unique_right + ~RegressionDiscontinuityResults.n_dropped + ~RegressionDiscontinuityResults.cutoff + ~RegressionDiscontinuityResults.p + ~RegressionDiscontinuityResults.q + ~RegressionDiscontinuityResults.kernel + ~RegressionDiscontinuityResults.bwselect + ~RegressionDiscontinuityResults.vcov_type + ~RegressionDiscontinuityResults.nnmatch + ~RegressionDiscontinuityResults.masspoints + ~RegressionDiscontinuityResults.bwcheck + ~RegressionDiscontinuityResults.bwrestrict + ~RegressionDiscontinuityResults.scaleregul + ~RegressionDiscontinuityResults.h_input + ~RegressionDiscontinuityResults.b_input + ~RegressionDiscontinuityResults.rho_input + ~RegressionDiscontinuityResults.estimand + ~RegressionDiscontinuityResults.sharpbw + ~RegressionDiscontinuityResults.treatment_col + ~RegressionDiscontinuityResults.covs_drop + diff --git a/docs/api/_autosummary/diff_diff.SpilloverDiDResults.rst b/docs/api/_autosummary/diff_diff.SpilloverDiDResults.rst index b49ee1ea2..d1582aec6 100644 --- a/docs/api/_autosummary/diff_diff.SpilloverDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.SpilloverDiDResults.rst @@ -33,17 +33,22 @@ ~SpilloverDiDResults.coefficients ~SpilloverDiDResults.conley_lag_cutoff ~SpilloverDiDResults.d_bar + ~SpilloverDiDResults.df_convention ~SpilloverDiDResults.event_study ~SpilloverDiDResults.event_study_effects ~SpilloverDiDResults.fitted_values ~SpilloverDiDResults.horizon_max + ~SpilloverDiDResults.inference_df ~SpilloverDiDResults.inference_method ~SpilloverDiDResults.is_significant ~SpilloverDiDResults.is_staggered ~SpilloverDiDResults.n_bootstrap ~SpilloverDiDResults.n_clusters ~SpilloverDiDResults.n_far_away_obs + ~SpilloverDiDResults.n_psu + ~SpilloverDiDResults.n_strata ~SpilloverDiDResults.n_units_ever_in_ring + ~SpilloverDiDResults.p_val_type ~SpilloverDiDResults.r_squared ~SpilloverDiDResults.reference_period ~SpilloverDiDResults.residuals diff --git a/docs/api/_autosummary/diff_diff.StackedDiDResults.rst b/docs/api/_autosummary/diff_diff.StackedDiDResults.rst index 73c3b0eb5..9134d07a9 100644 --- a/docs/api/_autosummary/diff_diff.StackedDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.StackedDiDResults.rst @@ -26,12 +26,17 @@ ~StackedDiDResults.alpha ~StackedDiDResults.anticipation ~StackedDiDResults.att + ~StackedDiDResults.balance + ~StackedDiDResults.balance_diagnostics ~StackedDiDResults.clean_control + ~StackedDiDResults.cluster_name ~StackedDiDResults.coef_var ~StackedDiDResults.conf_int + ~StackedDiDResults.covariates ~StackedDiDResults.is_significant ~StackedDiDResults.kappa_post ~StackedDiDResults.kappa_pre + ~StackedDiDResults.n_clusters ~StackedDiDResults.n_control_units ~StackedDiDResults.n_obs ~StackedDiDResults.n_stacked_obs @@ -42,6 +47,7 @@ ~StackedDiDResults.significance_stars ~StackedDiDResults.survey_metadata ~StackedDiDResults.t_stat + ~StackedDiDResults.vcov_type ~StackedDiDResults.weighting ~StackedDiDResults.overall_att ~StackedDiDResults.overall_se diff --git a/docs/api/_autosummary/diff_diff.StaggeredTripleDiffResults.rst b/docs/api/_autosummary/diff_diff.StaggeredTripleDiffResults.rst index dbcdbb5a2..c57948e32 100644 --- a/docs/api/_autosummary/diff_diff.StaggeredTripleDiffResults.rst +++ b/docs/api/_autosummary/diff_diff.StaggeredTripleDiffResults.rst @@ -43,6 +43,11 @@ ~StaggeredTripleDiffResults.group_effects ~StaggeredTripleDiffResults.influence_functions ~StaggeredTripleDiffResults.is_significant + ~StaggeredTripleDiffResults.overall_att_es + ~StaggeredTripleDiffResults.overall_conf_int_es + ~StaggeredTripleDiffResults.overall_p_value_es + ~StaggeredTripleDiffResults.overall_se_es + ~StaggeredTripleDiffResults.overall_t_stat_es ~StaggeredTripleDiffResults.p_value ~StaggeredTripleDiffResults.pscore_fallback ~StaggeredTripleDiffResults.pscore_trim @@ -56,11 +61,6 @@ ~StaggeredTripleDiffResults.overall_t_stat ~StaggeredTripleDiffResults.overall_p_value ~StaggeredTripleDiffResults.overall_conf_int - ~StaggeredTripleDiffResults.overall_att_es - ~StaggeredTripleDiffResults.overall_se_es - ~StaggeredTripleDiffResults.overall_t_stat_es - ~StaggeredTripleDiffResults.overall_p_value_es - ~StaggeredTripleDiffResults.overall_conf_int_es ~StaggeredTripleDiffResults.groups ~StaggeredTripleDiffResults.time_periods ~StaggeredTripleDiffResults.n_obs diff --git a/docs/api/_autosummary/diff_diff.SunAbrahamResults.rst b/docs/api/_autosummary/diff_diff.SunAbrahamResults.rst index 99be9bea6..3af9b3263 100644 --- a/docs/api/_autosummary/diff_diff.SunAbrahamResults.rst +++ b/docs/api/_autosummary/diff_diff.SunAbrahamResults.rst @@ -27,16 +27,21 @@ ~SunAbrahamResults.anticipation ~SunAbrahamResults.att ~SunAbrahamResults.bootstrap_results + ~SunAbrahamResults.cluster_name ~SunAbrahamResults.coef_var ~SunAbrahamResults.cohort_effects ~SunAbrahamResults.conf_int + ~SunAbrahamResults.conley_lag_cutoff ~SunAbrahamResults.control_group + ~SunAbrahamResults.event_study_vcov + ~SunAbrahamResults.event_study_vcov_index ~SunAbrahamResults.is_significant ~SunAbrahamResults.p_value ~SunAbrahamResults.se ~SunAbrahamResults.significance_stars ~SunAbrahamResults.survey_metadata ~SunAbrahamResults.t_stat + ~SunAbrahamResults.vcov_type ~SunAbrahamResults.event_study_effects ~SunAbrahamResults.overall_att ~SunAbrahamResults.overall_se diff --git a/docs/api/_autosummary/diff_diff.SyntheticControl.rst b/docs/api/_autosummary/diff_diff.SyntheticControl.rst index 3bb9c3b09..71e744743 100644 --- a/docs/api/_autosummary/diff_diff.SyntheticControl.rst +++ b/docs/api/_autosummary/diff_diff.SyntheticControl.rst @@ -1,4 +1,4 @@ -diff\_diff.SyntheticControl +diff\_diff.SyntheticControl =========================== .. currentmodule:: diff_diff @@ -19,18 +19,3 @@ diff\_diff.SyntheticControl - .. rubric:: Attributes - - .. autosummary:: - - ~SyntheticControl.v_method - ~SyntheticControl.custom_v - ~SyntheticControl.optimizer_options - ~SyntheticControl.n_starts - ~SyntheticControl.inner_max_iter - ~SyntheticControl.inner_min_decrease - ~SyntheticControl.standardize - ~SyntheticControl.alpha - ~SyntheticControl.seed - ~SyntheticControl.results_ - ~SyntheticControl.is_fitted_ diff --git a/docs/api/_autosummary/diff_diff.SyntheticControlResults.rst b/docs/api/_autosummary/diff_diff.SyntheticControlResults.rst index b39b5b905..0430df68c 100644 --- a/docs/api/_autosummary/diff_diff.SyntheticControlResults.rst +++ b/docs/api/_autosummary/diff_diff.SyntheticControlResults.rst @@ -1,4 +1,4 @@ -diff\_diff.SyntheticControlResults +diff\_diff.SyntheticControlResults ================================== .. currentmodule:: diff_diff @@ -12,10 +12,31 @@ diff\_diff.SyntheticControlResults .. autosummary:: ~SyntheticControlResults.__init__ + ~SyntheticControlResults.confidence_set + ~SyntheticControlResults.conformal_average_effect + ~SyntheticControlResults.conformal_confidence_intervals + ~SyntheticControlResults.conformal_test + ~SyntheticControlResults.get_confidence_set_df + ~SyntheticControlResults.get_conformal_ci_df + ~SyntheticControlResults.get_conformal_grid_df ~SyntheticControlResults.get_gap_df + ~SyntheticControlResults.get_in_time_placebo_df + ~SyntheticControlResults.get_in_time_placebo_gaps + ~SyntheticControlResults.get_leave_one_out_df + ~SyntheticControlResults.get_leave_one_out_gaps + ~SyntheticControlResults.get_placebo_df + ~SyntheticControlResults.get_regression_weights_df + ~SyntheticControlResults.get_sparse_synthetic_control_df + ~SyntheticControlResults.get_sparse_synthetic_control_gaps ~SyntheticControlResults.get_weights_df + ~SyntheticControlResults.in_space_placebo + ~SyntheticControlResults.in_time_placebo + ~SyntheticControlResults.leave_one_out ~SyntheticControlResults.print_summary + ~SyntheticControlResults.regression_weights + ~SyntheticControlResults.sparse_synthetic_control ~SyntheticControlResults.summary + ~SyntheticControlResults.test_sharp_null ~SyntheticControlResults.to_dataframe ~SyntheticControlResults.to_dict @@ -28,10 +49,17 @@ diff\_diff.SyntheticControlResults ~SyntheticControlResults.alpha ~SyntheticControlResults.coef_var + ~SyntheticControlResults.effect_confidence_set ~SyntheticControlResults.is_significant ~SyntheticControlResults.mspe_v + ~SyntheticControlResults.n_failed + ~SyntheticControlResults.n_infeasible + ~SyntheticControlResults.n_placebos + ~SyntheticControlResults.placebo_p_value + ~SyntheticControlResults.rmspe_ratio ~SyntheticControlResults.significance_stars ~SyntheticControlResults.survey_metadata + ~SyntheticControlResults.v_cv_t0 ~SyntheticControlResults.att ~SyntheticControlResults.se ~SyntheticControlResults.t_stat @@ -51,3 +79,4 @@ diff\_diff.SyntheticControlResults ~SyntheticControlResults.post_periods ~SyntheticControlResults.v_method ~SyntheticControlResults.standardize + diff --git a/docs/api/_autosummary/diff_diff.TROPResults.rst b/docs/api/_autosummary/diff_diff.TROPResults.rst index 2186f45b2..7a4f9c265 100644 --- a/docs/api/_autosummary/diff_diff.TROPResults.rst +++ b/docs/api/_autosummary/diff_diff.TROPResults.rst @@ -34,6 +34,7 @@ ~TROPResults.n_bootstrap ~TROPResults.n_post_periods ~TROPResults.n_pre_periods + ~TROPResults.non_absorbing ~TROPResults.significance_stars ~TROPResults.survey_metadata ~TROPResults.att diff --git a/docs/api/_autosummary/diff_diff.TripleDifferenceResults.rst b/docs/api/_autosummary/diff_diff.TripleDifferenceResults.rst index 991fe9dd3..d57a7d52a 100644 --- a/docs/api/_autosummary/diff_diff.TripleDifferenceResults.rst +++ b/docs/api/_autosummary/diff_diff.TripleDifferenceResults.rst @@ -26,6 +26,7 @@ .. autosummary:: ~TripleDifferenceResults.alpha + ~TripleDifferenceResults.cluster_name ~TripleDifferenceResults.covariate_balance ~TripleDifferenceResults.epv_diagnostics ~TripleDifferenceResults.epv_threshold @@ -39,6 +40,7 @@ ~TripleDifferenceResults.r_squared ~TripleDifferenceResults.significance_stars ~TripleDifferenceResults.survey_metadata + ~TripleDifferenceResults.vcov_type ~TripleDifferenceResults.att ~TripleDifferenceResults.se ~TripleDifferenceResults.t_stat diff --git a/docs/api/_autosummary/diff_diff.TwoStageDiD.rst b/docs/api/_autosummary/diff_diff.TwoStageDiD.rst index 73311ad64..a89f28fdf 100644 --- a/docs/api/_autosummary/diff_diff.TwoStageDiD.rst +++ b/docs/api/_autosummary/diff_diff.TwoStageDiD.rst @@ -30,5 +30,5 @@ ~TwoStageDiD.alpha ~TwoStageDiD.seed ~TwoStageDiD.horizon_max - ~TwoStageDiD.vcov_type + ~TwoStageDiD.pretrends diff --git a/docs/api/_autosummary/diff_diff.TwoStageDiDResults.rst b/docs/api/_autosummary/diff_diff.TwoStageDiDResults.rst index c57d1fc34..6c340e7f5 100644 --- a/docs/api/_autosummary/diff_diff.TwoStageDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.TwoStageDiDResults.rst @@ -28,14 +28,17 @@ ~TwoStageDiDResults.anticipation ~TwoStageDiDResults.att ~TwoStageDiDResults.bootstrap_results + ~TwoStageDiDResults.cluster_name ~TwoStageDiDResults.coef_var ~TwoStageDiDResults.conf_int ~TwoStageDiDResults.is_significant + ~TwoStageDiDResults.n_clusters ~TwoStageDiDResults.p_value ~TwoStageDiDResults.se ~TwoStageDiDResults.significance_stars ~TwoStageDiDResults.survey_metadata ~TwoStageDiDResults.t_stat + ~TwoStageDiDResults.vcov_type ~TwoStageDiDResults.treatment_effects ~TwoStageDiDResults.overall_att ~TwoStageDiDResults.overall_se @@ -51,7 +54,4 @@ ~TwoStageDiDResults.n_untreated_obs ~TwoStageDiDResults.n_treated_units ~TwoStageDiDResults.n_control_units - ~TwoStageDiDResults.vcov_type - ~TwoStageDiDResults.cluster_name - ~TwoStageDiDResults.n_clusters diff --git a/docs/api/_autosummary/diff_diff.WildBootstrapResults.rst b/docs/api/_autosummary/diff_diff.WildBootstrapResults.rst index d09127d76..20fb20348 100644 --- a/docs/api/_autosummary/diff_diff.WildBootstrapResults.rst +++ b/docs/api/_autosummary/diff_diff.WildBootstrapResults.rst @@ -24,6 +24,7 @@ ~WildBootstrapResults.alpha ~WildBootstrapResults.bootstrap_distribution + ~WildBootstrapResults.p_val_type ~WildBootstrapResults.se ~WildBootstrapResults.p_value ~WildBootstrapResults.t_stat_original diff --git a/docs/api/_autosummary/diff_diff.changes_in_changes_results.ChangesInChangesResults.rst b/docs/api/_autosummary/diff_diff.changes_in_changes_results.ChangesInChangesResults.rst new file mode 100644 index 000000000..18b4fb7ca --- /dev/null +++ b/docs/api/_autosummary/diff_diff.changes_in_changes_results.ChangesInChangesResults.rst @@ -0,0 +1,48 @@ +diff\_diff.changes\_in\_changes\_results.ChangesInChangesResults +================================================================ + +.. currentmodule:: diff_diff.changes_in_changes_results + +.. autoclass:: ChangesInChangesResults + :no-members: + + + .. rubric:: Methods + + .. autosummary:: + + ~ChangesInChangesResults.__init__ + ~ChangesInChangesResults.print_summary + ~ChangesInChangesResults.summary + ~ChangesInChangesResults.to_dataframe + ~ChangesInChangesResults.to_dict + ~ChangesInChangesResults.uniform_bands + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~ChangesInChangesResults.alpha + ~ChangesInChangesResults.covariates + ~ChangesInChangesResults.is_significant + ~ChangesInChangesResults.significance_stars + ~ChangesInChangesResults.att + ~ChangesInChangesResults.se + ~ChangesInChangesResults.t_stat + ~ChangesInChangesResults.p_value + ~ChangesInChangesResults.conf_int + ~ChangesInChangesResults.quantile_effects + ~ChangesInChangesResults.q_lower + ~ChangesInChangesResults.q_upper + ~ChangesInChangesResults.sup_t_crit + ~ChangesInChangesResults.n_obs + ~ChangesInChangesResults.cell_sizes + ~ChangesInChangesResults.n_bootstrap + ~ChangesInChangesResults.n_bootstrap_valid + ~ChangesInChangesResults.panel + ~ChangesInChangesResults.estimator + ~ChangesInChangesResults.quantiles + diff --git a/docs/api/_autosummary/diff_diff.wooldridge_results.WooldridgeDiDResults.rst b/docs/api/_autosummary/diff_diff.wooldridge_results.WooldridgeDiDResults.rst index 228e21ffa..8bc82818d 100644 --- a/docs/api/_autosummary/diff_diff.wooldridge_results.WooldridgeDiDResults.rst +++ b/docs/api/_autosummary/diff_diff.wooldridge_results.WooldridgeDiDResults.rst @@ -28,11 +28,15 @@ ~WooldridgeDiDResults.anticipation ~WooldridgeDiDResults.att ~WooldridgeDiDResults.calendar_effects + ~WooldridgeDiDResults.cluster_name + ~WooldridgeDiDResults.cohort_trends ~WooldridgeDiDResults.conf_int + ~WooldridgeDiDResults.conley_lag_cutoff ~WooldridgeDiDResults.control_group ~WooldridgeDiDResults.event_study_effects ~WooldridgeDiDResults.group_effects ~WooldridgeDiDResults.method + ~WooldridgeDiDResults.n_clusters ~WooldridgeDiDResults.n_control_units ~WooldridgeDiDResults.n_obs ~WooldridgeDiDResults.n_treated_units @@ -40,6 +44,7 @@ ~WooldridgeDiDResults.se ~WooldridgeDiDResults.survey_metadata ~WooldridgeDiDResults.t_stat + ~WooldridgeDiDResults.vcov_type ~WooldridgeDiDResults.group_time_effects ~WooldridgeDiDResults.overall_att ~WooldridgeDiDResults.overall_se @@ -48,4 +53,6 @@ ~WooldridgeDiDResults.overall_conf_int ~WooldridgeDiDResults.groups ~WooldridgeDiDResults.time_periods + ~WooldridgeDiDResults.cohort_trend_coefs + ~WooldridgeDiDResults.aggregation_weights diff --git a/docs/api/index.rst b/docs/api/index.rst index 789cfc57b..6301c5449 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -6,7 +6,8 @@ This section provides complete API documentation for all diff-diff modules. Estimators ---------- -Core estimator classes for DiD analysis: +Core causal-inference estimator classes - the DiD family plus synthetic control, +regression discontinuity, and the Goodman-Bacon decomposition diagnostic: .. autosummary:: :toctree: _autosummary @@ -35,6 +36,7 @@ Core estimator classes for DiD analysis: diff_diff.QDiD diff_diff.BaconDecomposition diff_diff.StaggeredTripleDifference + diff_diff.RegressionDiscontinuity Results Classes --------------- @@ -78,11 +80,13 @@ Result containers returned by estimators: diff_diff.Comparison2x2 diff_diff.StaggeredTripleDiffResults diff_diff.TWFEWeightsResult + diff_diff.RegressionDiscontinuityResults + diff_diff.RDPlotResult Visualization ------------- -Plotting functions for results: +Plotting functions and plot builders: .. autosummary:: :toctree: _autosummary @@ -92,6 +96,7 @@ Plotting functions for results: diff_diff.plot_group_effects diff_diff.plot_sensitivity diff_diff.plot_honest_event_study + diff_diff.RDPlot diff_diff.plot_bacon diff_diff.plot_power_curve diff_diff.plot_pretrends_power diff --git a/docs/conf.py b/docs/conf.py index 2491fa050..cb0c064fe 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,6 +31,7 @@ "sphinx_sitemap", "nbsphinx", "myst_parser", + "sphinx_design", ] # MyST renders the two in-site methodology markdown pages (REGISTRY.md, @@ -93,7 +94,10 @@ # -- Options for HTML output ------------------------------------------------- html_theme = "pydata_sphinx_theme" html_static_path = ["_static"] -html_title = "diff-diff: Difference-in-Differences Causal Inference for Python" +html_title = "diff-diff documentation" +# The homepage is a full-width card-grid landing page; suppress the (empty) +# primary sidebar rail there. Matches only the root docname. +html_sidebars = {"index": []} # Use RTD's canonical URL when available; fall back to stable for local builds. _canonical_url = os.environ.get( "READTHEDOCS_CANONICAL_URL", diff --git a/docs/getting_started.rst b/docs/getting_started.rst new file mode 100644 index 000000000..7c67040e3 --- /dev/null +++ b/docs/getting_started.rst @@ -0,0 +1,41 @@ +.. meta:: + :description: Get started with diff-diff — install the package, run your first Difference-in-Differences analysis, and choose the right estimator for your design. + :keywords: diff-diff getting started, DiD python install, choose DiD estimator + +Getting Started +=============== + +New to diff-diff? Start here: install the package, run your first analysis, +and learn which estimator fits your research design. + +.. grid:: 1 2 2 3 + :gutter: 3 + + .. grid-item-card:: Quickstart + :link: quickstart + :link-type: doc + + Installation and your first DiD analysis — column-name and formula + interfaces, covariates, and robust inference. + + .. grid-item-card:: Choosing an Estimator + :link: choosing_estimator + :link-type: doc + + A decision flowchart that maps your research design to the right + estimator, from basic 2x2 DiD to staggered adoption methods. + + .. grid-item-card:: Troubleshooting + :link: troubleshooting + :link-type: doc + + Solutions for common issues: singular matrices, collinear covariates, + insufficient variation, and convergence problems. + +.. toctree:: + :maxdepth: 2 + :hidden: + + quickstart + Choosing an Estimator + troubleshooting diff --git a/docs/index.rst b/docs/index.rst index 681e81e0a..17b414d83 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -20,7 +20,7 @@ It provides sklearn-like estimators with statsmodels-style output for econometri Key Features ------------ -- **13+ Estimators**: Basic DiD, TWFE, Event Study, Synthetic DiD, plus modern staggered estimators (Callaway-Sant'Anna, Sun-Abraham, Imputation, Two-Stage, Stacked DiD), advanced methods (TROP, Continuous DiD, Efficient DiD, Triple Difference), and Bacon Decomposition diagnostics +- **20+ Estimators**: Basic DiD, TWFE, Event Study, Synthetic DiD/Control, modern staggered estimators (Callaway-Sant'Anna, Sun-Abraham, Imputation, Two-Stage, Stacked, LP-DiD), reversible and heterogeneous-adoption designs (dCDH, HAD), distributional methods (Changes-in-Changes), Regression Discontinuity, and Bacon Decomposition diagnostics - **Modern Inference**: Robust standard errors, cluster-robust SEs, wild cluster bootstrap, and multiplier bootstrap - **Assumption Testing**: Parallel trends tests, placebo tests, Bacon decomposition, and comprehensive diagnostics - **Sensitivity Analysis**: Honest DiD (Rambachan & Roth 2023) for robust inference under parallel trends violations @@ -54,99 +54,56 @@ Quick Links - :doc:`r_comparison` - Coming from R? - :doc:`api/index` - Full API reference -.. toctree:: - :maxdepth: 2 - :caption: For Data Scientists - :hidden: +Explore the Documentation +------------------------- - Practitioner Guide - Decision Tree +.. grid:: 1 2 2 3 + :gutter: 3 -.. toctree:: - :maxdepth: 2 - :caption: Getting Started - :hidden: + .. grid-item-card:: Getting Started + :link: getting_started + :link-type: doc - quickstart - Estimator Guide - troubleshooting - references + Install, run your first DiD analysis, and pick the right estimator + for your design. -.. toctree:: - :maxdepth: 1 - :caption: Tutorials: Business Applications - :hidden: - - tutorials/17_brand_awareness_survey - tutorials/18_geo_experiments - tutorials/19_dcdh_marketing_pulse - tutorials/20_had_brand_campaign - tutorials/21_had_pretest_workflow - tutorials/22_had_survey_design - tutorials/23_spillover_tva - tutorials/26_composition_drift_calibration - tutorials/27_cic_distributional_effects - -.. toctree:: - :maxdepth: 1 - :caption: Tutorials: Fundamentals - :hidden: + .. grid-item-card:: Practitioner Guide + :link: practitioners + :link-type: doc - tutorials/01_basic_did - tutorials/02_staggered_did - tutorials/03_synthetic_did - tutorials/08_triple_diff - tutorials/09_real_world_examples + Measuring campaign impact? A business-first path through DiD, no + econometrics background required. -.. toctree:: - :maxdepth: 1 - :caption: Tutorials: Advanced Methods - :hidden: + .. grid-item-card:: Tutorials + :link: tutorials/index + :link-type: doc - tutorials/10_trop - tutorials/11_imputation_did - tutorials/12_two_stage_did - tutorials/13_stacked_did - tutorials/14_continuous_did - tutorials/15_efficient_did - tutorials/16_survey_did - tutorials/16_wooldridge_etwfe - tutorials/25_synthetic_control_policy + 28 hands-on notebooks, from basic 2x2 DiD to survey-weighted and + spillover-aware designs. -.. toctree:: - :maxdepth: 1 - :caption: Tutorials: Study Design - :hidden: + .. grid-item-card:: User Guide + :link: user_guide + :link-type: doc - tutorials/04_parallel_trends - tutorials/05_honest_did - tutorials/06_power_analysis - tutorials/07_pretrends_power - tutorials/24_staggered_vs_collapsed_power + References, R and Python comparisons, benchmarks, and the + methodology registry. -.. toctree:: - :maxdepth: 1 - :caption: Comparisons & Benchmarks - :hidden: + .. grid-item-card:: API Reference + :link: api/index + :link-type: doc - r_comparison - python_comparison - benchmarks + Complete reference for all estimators, results classes, diagnostics, + and utilities. .. toctree:: :maxdepth: 2 - :caption: API Reference - :hidden: - - api/index - -.. toctree:: - :maxdepth: 1 - :caption: Methodology :hidden: - methodology/REGISTRY - methodology/REPORTING + Getting Started + Practitioner Guide + Tutorials + User Guide + API Reference What is Difference-in-Differences? ---------------------------------- @@ -159,7 +116,7 @@ public policy evaluation, and social science research. Why diff-diff? -------------- -- **Complete method coverage**: 13+ estimators from basic 2x2 DiD to cutting-edge methods like Efficient DiD (Chen et al. 2025) and TROP (Athey et al. 2025) +- **Complete method coverage**: 20+ estimators from basic 2x2 DiD to cutting-edge methods like Efficient DiD (Chen et al. 2025), TROP (Athey et al. 2025), and HAD (de Chaisemartin et al. 2026) - **Familiar API**: sklearn-like ``fit()`` interface — if you know scikit-learn, you know diff-diff - **Modern staggered methods**: Callaway-Sant'Anna, Sun-Abraham, Imputation DiD, Two-Stage DiD, and Stacked DiD handle heterogeneous treatment timing correctly - **Robust inference**: Heteroskedasticity-robust, cluster-robust, wild cluster bootstrap, and multiplier bootstrap @@ -183,7 +140,9 @@ Supported Estimators * - :class:`~diff_diff.MultiPeriodDiD` - Event study with period-specific treatment effects * - :class:`~diff_diff.CallawaySantAnna` - - Callaway & Sant'Anna (2021) for staggered adoption + - Callaway & Sant'Anna (2021) group-time ATT for staggered adoption + * - :class:`~diff_diff.ChaisemartinDHaultfoeuille` + - de Chaisemartin & D'Haultfoeuille (2020/2022) for reversible (non-absorbing) treatments * - :class:`~diff_diff.SunAbraham` - Sun & Abraham (2021) interaction-weighted estimator * - :class:`~diff_diff.ImputationDiD` @@ -194,14 +153,30 @@ Supported Estimators - Butts (2021) ring-indicator spillover-aware DiD * - :class:`~diff_diff.SyntheticDiD` - Synthetic DiD combining DiD and synthetic control + * - :class:`~diff_diff.SyntheticControl` + - Abadie, Diamond & Hainmueller (2010) classic synthetic control * - :class:`~diff_diff.StackedDiD` - Wing, Freedman & Hollingsworth (2024) stacked DiD * - :class:`~diff_diff.EfficientDiD` - Chen, Sant'Anna & Xie (2025) efficient DiD * - :class:`~diff_diff.TripleDifference` - Triple difference (DDD) estimator + * - :class:`~diff_diff.StaggeredTripleDifference` + - Ortiz-Villavicencio & Sant'Anna (2025) staggered DDD with group-time ATT * - :class:`~diff_diff.ContinuousDiD` - - Continuous treatment DiD + - Callaway, Goodman-Bacon & Sant'Anna (2024) continuous-treatment dose-response DiD + * - :class:`~diff_diff.HeterogeneousAdoptionDiD` + - de Chaisemartin, Ciccia, D'Haultfoeuille & Knau (2026) for designs with no untreated units + * - :class:`~diff_diff.LPDiD` + - Dube, Girardi, Jorda & Taylor (2025) local-projections DiD + * - :class:`~diff_diff.WooldridgeDiD` + - Wooldridge (2023, 2025) extended TWFE (ETWFE) via saturated OLS or QMLE + * - :class:`~diff_diff.ChangesInChanges` + - Athey & Imbens (2006) distributional DiD with quantile treatment effects + * - :class:`~diff_diff.QDiD` + - Quantile DiD comparison estimator applying DiD quantile-by-quantile + * - :class:`~diff_diff.RegressionDiscontinuity` + - Calonico, Cattaneo & Titiunik (2014) sharp/fuzzy RD with robust bias-corrected inference * - :class:`~diff_diff.TROP` - Triply Robust Panel with factor model adjustment (Athey et al. 2025) * - :class:`~diff_diff.BaconDecomposition` diff --git a/docs/practitioners.rst b/docs/practitioners.rst new file mode 100644 index 000000000..4178d0e5c --- /dev/null +++ b/docs/practitioners.rst @@ -0,0 +1,38 @@ +.. meta:: + :description: The diff-diff practitioner guide — measure campaign impact and business interventions with Difference-in-Differences, no econometrics background required. + :keywords: campaign impact measurement, marketing incrementality, DiD for data scientists + +Practitioner Guide +================== + +Measuring the impact of a campaign, product launch, or pricing change? This +track walks from business question to causal estimate without assuming an +econometrics background. + +.. grid:: 1 2 2 2 + :gutter: 3 + + .. grid-item-card:: Measuring Campaign Impact + :link: practitioner_getting_started + :link-type: doc + + An end-to-end walkthrough from marketing campaign to causal estimate + to stakeholder-ready result. + + .. grid-item-card:: Which Method Fits Your Problem? + :link: practitioner_decision_tree + :link-type: doc + + Start from your business scenario — simultaneous launch, staggered + rollout, on/off pulses, survey data — and find the right estimator. + +Looking for worked examples? The :doc:`Business Applications tutorials +` cover geo-experiments, brand campaigns, survey-weighted +designs, and spillover-aware analyses end to end. + +.. toctree:: + :maxdepth: 2 + :hidden: + + Measuring Campaign Impact + Which Method Fits Your Problem? diff --git a/docs/quickstart.rst b/docs/quickstart.rst index af91072ab..7a4770437 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -2,8 +2,10 @@ :description: Get started with diff-diff for Difference-in-Differences analysis in Python. Step-by-step tutorial covering basic DiD, formulas, covariates, and robust inference. :keywords: difference-in-differences tutorial, DiD python getting started, causal inference quickstart -Getting Started -=============== +.. _getting-started: + +Quickstart +========== This guide will help you get started with diff-diff for Difference-in-Differences analysis. diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst new file mode 100644 index 000000000..6fa205e45 --- /dev/null +++ b/docs/tutorials/index.rst @@ -0,0 +1,284 @@ +.. meta:: + :description: Hands-on diff-diff tutorials — 28 Jupyter notebooks covering basic 2x2 DiD, staggered adoption, synthetic DiD, power analysis, and business applications. + :keywords: DiD tutorial, difference-in-differences examples, causal inference notebooks + +Tutorials +========= + +Every tutorial is a runnable Jupyter notebook. If you are new to diff-diff, +start with :doc:`Basic DiD <01_basic_did>`; if you are measuring a business +intervention, start with the Business Applications track. + +Business Applications +--------------------- + +Practitioner walkthroughs built around marketing and policy scenarios. + +.. grid:: 1 2 2 3 + :gutter: 3 + + .. grid-item-card:: Brand Awareness Surveys + :link: 17_brand_awareness_survey + :link-type: doc + + Measure campaign impact on brand awareness with complex survey data + and staggered rollouts. + + .. grid-item-card:: Geo-Experiments + :link: 18_geo_experiments + :link-type: doc + + Measure lift from a campaign that ran in a subset of geographic + markets using Synthetic DiD. + + .. grid-item-card:: dCDH Marketing Pulse + :link: 19_dcdh_marketing_pulse + :link-type: doc + + Analyze on/off pulse campaigns with the de Chaisemartin-D'Haultfoeuille + estimator for reversible treatments. + + .. grid-item-card:: HAD Brand Campaign + :link: 20_had_brand_campaign + :link-type: doc + + Estimate per-dollar lift when every market receives a different spend + intensity. + + .. grid-item-card:: HAD Pre-test Workflow + :link: 21_had_pretest_workflow + :link-type: doc + + Run the pre-test diagnostics on the brand-campaign panel before + trusting the estimate. + + .. grid-item-card:: Survey-Weighted HAD + :link: 22_had_survey_design + :link-type: doc + + Heterogeneous-adoption DiD on a BRFSS-shape survey rollout with design + weights. + + .. grid-item-card:: Spillover DiD (TVA) + :link: 23_spillover_tva + :link-type: doc + + Handle treatment that spills over onto nearby control units in a + TVA-style worked example. + + .. grid-item-card:: Composition Drift & Calibration + :link: 26_composition_drift_calibration + :link-type: doc + + Survey calibration for causal DiD when who answers changes over time. + + .. grid-item-card:: Distributional Effects (CiC) + :link: 27_cic_distributional_effects + :link-type: doc + + See which quantiles moved when the average hides the action, with + Changes-in-Changes. + +.. toctree:: + :maxdepth: 1 + :caption: Business Applications + :hidden: + + Brand Awareness Surveys <17_brand_awareness_survey> + Geo-Experiments <18_geo_experiments> + dCDH Marketing Pulse <19_dcdh_marketing_pulse> + HAD Brand Campaign <20_had_brand_campaign> + HAD Pre-test Workflow <21_had_pretest_workflow> + Survey-Weighted HAD <22_had_survey_design> + Spillover DiD (TVA) <23_spillover_tva> + Composition Drift & Calibration <26_composition_drift_calibration> + Distributional Effects (CiC) <27_cic_distributional_effects> + +Fundamentals +------------ + +The core DiD toolkit, from your first 2x2 design to real published datasets. + +.. grid:: 1 2 2 3 + :gutter: 3 + + .. grid-item-card:: Basic DiD + :link: 01_basic_did + :link-type: doc + + Your first 2x2 DiD: column-name and formula interfaces, covariates, + fixed effects, and robust inference. + + .. grid-item-card:: Staggered DiD + :link: 02_staggered_did + :link-type: doc + + Handle staggered treatment adoption with modern heterogeneity-robust + estimators. + + .. grid-item-card:: Synthetic DiD + :link: 03_synthetic_did + :link-type: doc + + Combine DiD with synthetic-control weighting (Arkhangelsky et al. + 2021). + + .. grid-item-card:: Triple Difference (DDD) + :link: 08_triple_diff + :link-type: doc + + Add a second comparison dimension when treatment requires satisfying + two criteria. + + .. grid-item-card:: Real-World Examples + :link: 09_real_world_examples + :link-type: doc + + Classic datasets end to end: Card & Krueger minimum wage, Castle + Doctrine, and more. + +.. toctree:: + :maxdepth: 1 + :caption: Fundamentals + :hidden: + + Basic DiD <01_basic_did> + Staggered DiD <02_staggered_did> + Synthetic DiD <03_synthetic_did> + Triple Difference (DDD) <08_triple_diff> + Real-World Examples <09_real_world_examples> + +Advanced Methods +---------------- + +Modern estimators for designs the basic toolkit cannot handle. + +.. grid:: 1 2 2 3 + :gutter: 3 + + .. grid-item-card:: TROP + :link: 10_trop + :link-type: doc + + Triply robust panel estimator with factor-model adjustment (Athey et + al. 2025). + + .. grid-item-card:: Imputation DiD + :link: 11_imputation_did + :link-type: doc + + The efficient imputation estimator of Borusyak, Jaravel & Spiess + (2024). + + .. grid-item-card:: Two-Stage DiD + :link: 12_two_stage_did + :link-type: doc + + Gardner (2022) two-stage residualized estimation for staggered + designs. + + .. grid-item-card:: Stacked DiD + :link: 13_stacked_did + :link-type: doc + + Stacked event studies with corrective weights (Wing, Freedman & + Hollingsworth 2024). + + .. grid-item-card:: Continuous DiD + :link: 14_continuous_did + :link-type: doc + + Dose-response treatment effects with continuous treatment intensity. + + .. grid-item-card:: Efficient DiD + :link: 15_efficient_did + :link-type: doc + + Semiparametrically efficient ATT estimation (Chen, Sant'Anna & Xie + 2025). + + .. grid-item-card:: Survey-Aware DiD + :link: 16_survey_did + :link-type: doc + + DiD on stratified survey microdata with design-based inference. + + .. grid-item-card:: Wooldridge ETWFE + :link: 16_wooldridge_etwfe + :link-type: doc + + Wooldridge's extended two-way fixed effects via pooled OLS. + + .. grid-item-card:: Synthetic Control for Policy + :link: 25_synthetic_control_policy + :link-type: doc + + Single-treated-unit policy evaluation with two routes to inference. + +.. toctree:: + :maxdepth: 1 + :caption: Advanced Methods + :hidden: + + TROP <10_trop> + Imputation DiD <11_imputation_did> + Two-Stage DiD <12_two_stage_did> + Stacked DiD <13_stacked_did> + Continuous DiD <14_continuous_did> + Efficient DiD <15_efficient_did> + Survey-Aware DiD <16_survey_did> + Wooldridge ETWFE <16_wooldridge_etwfe> + Synthetic Control for Policy <25_synthetic_control_policy> + +Study Design +------------ + +Assess identifying assumptions and size your study before committing to it. + +.. grid:: 1 2 2 3 + :gutter: 3 + + .. grid-item-card:: Parallel Trends Diagnostics + :link: 04_parallel_trends + :link-type: doc + + Assess pre-treatment evidence relevant to parallel trends, check + test power, and run the full diagnostic suite. + + .. grid-item-card:: Honest DiD Sensitivity + :link: 05_honest_did + :link-type: doc + + Robust inference under parallel-trends violations (Rambachan & Roth + 2023). + + .. grid-item-card:: Power Analysis + :link: 06_power_analysis + :link-type: doc + + Compute minimum detectable effects and sample sizes before running + the study. + + .. grid-item-card:: Pre-Trends Power + :link: 07_pretrends_power + :link-type: doc + + Check whether your pre-trends test can actually detect violations + (Roth 2022). + + .. grid-item-card:: Staggered vs Collapsed Power + :link: 24_staggered_vs_collapsed_power + :link-type: doc + + Staggered rollout or a simple 2x2? A power-analysis decision guide. + +.. toctree:: + :maxdepth: 1 + :caption: Study Design + :hidden: + + Parallel Trends Diagnostics <04_parallel_trends> + Honest DiD Sensitivity <05_honest_did> + Power Analysis <06_power_analysis> + Pre-Trends Power <07_pretrends_power> + Staggered vs Collapsed Power <24_staggered_vs_collapsed_power> diff --git a/docs/user_guide.rst b/docs/user_guide.rst new file mode 100644 index 000000000..742f5289e --- /dev/null +++ b/docs/user_guide.rst @@ -0,0 +1,64 @@ +.. meta:: + :description: The diff-diff user guide — scholarly references, validation against R and Python packages, benchmarks, and the full methodology registry. + :keywords: DiD methodology, R did package comparison, DiD benchmarks, econometrics references + +User Guide +========== + +The methods behind the library: scholarly references, validation against R +and Python implementations, performance benchmarks, and the methodology +registry documenting every estimator's equations and edge cases. + +.. grid:: 1 2 2 3 + :gutter: 3 + + .. grid-item-card:: References + :link: references + :link-type: doc + + Scholarly citations for every estimator and diagnostic in the + library. + + .. grid-item-card:: R Comparison + :link: r_comparison + :link-type: doc + + Coming from R? Side-by-side workflows and numerical validation + against ``did``, ``synthdid``, and ``fixest``. + + .. grid-item-card:: Python Comparison + :link: python_comparison + :link-type: doc + + How diff-diff compares to other Python causal-inference libraries. + + .. grid-item-card:: Benchmarks + :link: benchmarks + :link-type: doc + + Validation results and performance benchmarks against reference + implementations. + + .. grid-item-card:: Methodology Registry + :link: methodology/REGISTRY + :link-type: doc + + Academic foundations, equations, and documented edge cases for every + estimator. + + .. grid-item-card:: Reporting + :link: methodology/REPORTING + :link-type: doc + + Conventions for reporting DiD results. + +.. toctree:: + :maxdepth: 1 + :hidden: + + references + R Comparison + Python Comparison + benchmarks + Methodology Registry + Reporting diff --git a/pyproject.toml b/pyproject.toml index b08ee47b4..d3170d07f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,6 +82,9 @@ docs = [ "sphinx-sitemap>=2.5", "nbsphinx>=0.9", "myst-parser>=2.0", + # sphinx-design floor stays at 0.6.1: 0.7.0 requires Python >=3.11 and + # the docs dep set must still resolve on the 3.9 CI smoke job. + "sphinx-design>=0.6.1", "matplotlib>=3.5", # ipython provides the 'ipython3' Pygments lexer used by nbsphinx for # notebook code cells; without it Sphinx emits highlighting_failure