Heterogeneous treatment effects in regression discontinuity designs.
Project description
rdhte (Python)
Heterogeneous treatment effects in regression discontinuity (RD) designs. Point estimates, robust bias-corrected confidence intervals, and heteroskedastic or cluster-robust standard errors for conditional RD treatment effects.
The theoretical framework is developed in Calonico, Cattaneo, Farrell, Palomba, and Titiunik (2025). arXiv
Install (development)
cd Python/rdhte
pip install -e ".[plot,test]"
Hard dependencies: numpy, scipy, pandas, statsmodels, rdrobust.
Plotting (rdhte.plot.plot) additionally requires plotnine.
Quick start
import numpy as np
from rdhte import rdhte, rdbwhte, rdhte_lincom
rng = np.random.default_rng(0)
n = 5000
x = rng.uniform(-1.0, 1.0, n)
W = np.where(rng.random(n) < 0.5, "A", "B") # categorical W
y = ((x >= 0) * (1.0 + 0.5 * (W == "B")) # CATE = 1.0 (A), 1.5 (B)
+ 0.3 * x + rng.normal(0, 0.3, n))
# Per-cell CATEs with rdrobust-style bandwidth selection (default: mserd).
m = rdhte(y=y, x=x, c=0.0, covs_hte=W)
print(m) # short header
print(m.summary()) # full table with Nh/h columns
print(m.tidy()) # broom-style DataFrame: term, estimate, std.error, ...
print(m.glance()) # one-row metadata DataFrame
# Data-driven bandwidth per cell, without running the full estimator.
bw = rdbwhte(y=y, x=x, c=0.0, covs_hte=W)
print(bw.h) # (n_lev, 2) array of left/right bandwidths
# Test H0: CATE(A) == CATE(B), and separately H0: CATE(A) == 0.
res = rdhte_lincom(m, linfct=["A - B = 0", "A = 0"])
print(res["individual"])
print(res["joint"])
Empirical illustration
The package includes a full empirical illustration using the bundled
Granzier, Pons, and Tricaud election dataset.
From the Python folder:
python rdhte_illustration.py
Command Reference
The companion commands are:
| Command | Purpose |
|---|---|
rdhte() |
Estimate conditional RD treatment effects and robust bias-corrected inference. |
rdbwhte() |
Compute data-driven left/right bandwidths without running the full estimator. |
rdhte_lincom() |
Test linear restrictions of the fitted CATE vector. |
Main estimation options:
| Option | Notes |
|---|---|
covs_hte |
Heterogeneity covariates. Accepts no covariate, one categorical/continuous variable, a list/DataFrame/2-D array for Cartesian-product cells, or a formula string with data=. |
c, p, q |
RD cutoff and local-polynomial orders. Default p=1; q=None resolves to p + 1. |
h, h_l, h_r |
Manual common or side-specific bandwidths. If omitted, rdrobust.rdbwselect is called using bwselect. |
kernel |
triangular, epanechnikov, or uniform (tri, epa, uni also accepted). |
weights |
Non-negative unit weights multiplying the kernel weights. |
covs_eff |
Efficiency-improving covariates, included additively and through W interactions; they do not define CATE cells. |
vce, cluster |
hc0-hc3 without clusters; cr1-cr3 with cluster=. Legacy hc* plus cluster= is remapped to the matching cr* with a warning. |
level |
Confidence level in percent, e.g. 95, not 0.95. |
bwjoint |
For categorical covs_hte, force one shared bandwidth across groups. Continuous/formula paths already use a shared bandwidth. |
data, subset |
Resolve column-name strings against a DataFrame and optionally keep a subset of rows. |
bwselect accepts mserd, msetwo, msesum, msecomb1, msecomb2,
cerrd, certwo, cersum, cercomb1, and cercomb2. MSE denotes
mean square error; CER denotes coverage error rate.
Return Objects
rdhte() returns an RdhteResult with fields for estimates, inference
results, bandwidths, labels, and metadata:
Estimate, Estimate_bc, coef, coef_bc, se_rb, ci_rb, t_rb,
pv_rb, vcov, W_lev, W_names, kernel, bwselect, vce,
vce_select, c, h, p, q, N, Nh, level, and rdmodel.
Convenience methods include summary(), tidy(), and glance().
rdbwhte() returns an RdbwhteResult with bandwidths h, effective
sample sizes Nh, group labels, and the same metadata. rdhte_lincom()
returns a dictionary with individual and joint test-result DataFrames.
Multiple heterogeneity variables
For factor-by-factor interactions and formula expressions, supply
covs_hte as a list of arrays / DataFrame / formula string:
import pandas as pd
df = pd.DataFrame({"y": y, "x": x, "W1": W1, "W2": W2})
# Cartesian-product factor cells.
m_2d = rdhte(y="y", x="x", c=0.0, covs_hte=[df["W1"], df["W2"]], data=df)
# Formula syntax (linear-in-Wk CATE per term).
m_form = rdhte(y="y", x="x", c=0.0, covs_hte="W1 * W2", data=df)
# Coefs: T, T:W1, T:W2, T:W1.W2.
# factor() is accepted as an alias for patsy C().
m_mix = rdhte(y="y", x="x", c=0.0, covs_hte="factor(W1) * W2", data=df)
Supported Features
| Feature | Status |
|---|---|
Categorical covs_hte (one variable) |
yes |
Continuous covs_hte (single numeric column) |
yes |
No covs_hte (ATE-only path) |
yes |
Manual bandwidth (h=) or per-side h_l/h_r |
yes |
rdrobust.rdbwselect automatic bandwidth |
yes |
Cluster-robust SE (cluster=, vce="cr1"/cr2/cr3) |
yes |
Heteroskedastic SE (vce="hc0"/hc1/hc2/hc3) |
yes |
| Robust bias correction (q-order parallel fit) | yes |
Linear-combination tests (rdhte_lincom) |
yes |
Forest plot for categorical W (rdhte.plot.plot) |
yes |
summary() / tidy() / glance() methods |
yes |
Factor-by-factor interaction covs_hte |
yes (pass [W1, W2] / pd.DataFrame / 2-D ndarray) |
Formula-string covs_hte (e.g. "w_left*w_strength") |
yes (requires data=; factor(X) is accepted as an alias for patsy C(X)) |
covs_eff (efficiency-improving covariates) |
yes (1-D / 2-D / DataFrame; enters additively + W interactions; never with T or Xp) |
vce accepts: nn, hc0, hc1, hc2, hc3, cr1, cr2, cr3.
When cluster= is supplied the default switches to cr1; passing an
hc* value with a cluster issues a warning and upgrades to the
matching cr* form.
References
- Calonico, Cattaneo, Farrell, Palomba, and Titiunik (2025a): Treatment Effect Heterogeneity in Regression Discontinuity Designs.
- Calonico, Cattaneo, Farrell, Palomba, and Titiunik (2025b): rdhte: Conditional Average Treatment Effects in RD Designs.
- Cattaneo and Titiunik (2022): Regression Discontinuity Designs.
- Calonico, Cattaneo, and Farrell (2020): Optimal Bandwidth Choice for Robust Bias Corrected Inference in Regression Discontinuity Designs.
- Calonico, Cattaneo, Farrell, and Titiunik (2019): Regression Discontinuity Designs using Covariates.
- Calonico, Cattaneo, and Titiunik (2014): Robust Nonparametric Confidence Intervals for Regression-Discontinuity Designs.
- Granzier, Pons, and Tricaud (2023): Coordination and Bandwagon Effects: How Past Rankings Shape the Behavior of Voters and Candidates.
Related RD software is available at https://rdpackages.github.io/.
Authors
Sebastian Calonico, Matias D. Cattaneo, Max H. Farrell, Filippo Palomba, Rocio Titiunik.
License
GPL-3; see LICENSE in this package and LICENSE.md at the repository root.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rdhte-0.1.0.tar.gz.
File metadata
- Download URL: rdhte-0.1.0.tar.gz
- Upload date:
- Size: 40.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18cf474acbf6d5f5374dcedcc3779743cc831c35e65b3cf7497a8cdee592cdf6
|
|
| MD5 |
f456918e8a92241b3f0758b324f2ef1a
|
|
| BLAKE2b-256 |
addf1a80eee360cc406c8e536b817b6082a421f608a351e4ef9cd51c257aa2bb
|
Provenance
The following attestation bundles were made for rdhte-0.1.0.tar.gz:
Publisher:
publish-python.yml on rdpackages/rdhte
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rdhte-0.1.0.tar.gz -
Subject digest:
18cf474acbf6d5f5374dcedcc3779743cc831c35e65b3cf7497a8cdee592cdf6 - Sigstore transparency entry: 1601886527
- Sigstore integration time:
-
Permalink:
rdpackages/rdhte@ba64a3aa16f91e68e7ac287f56f424db6705cac0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/rdpackages
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@ba64a3aa16f91e68e7ac287f56f424db6705cac0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rdhte-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rdhte-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08f701b7c2f40c40290426828c13af7cbc370408b2ac24357387e0c63d3955a8
|
|
| MD5 |
67155551df5af794a0406b74b9fa2e5f
|
|
| BLAKE2b-256 |
732791b7e0c23546e02a6a857581e83de9117a3962efedadd2a83082f0c6e404
|
Provenance
The following attestation bundles were made for rdhte-0.1.0-py3-none-any.whl:
Publisher:
publish-python.yml on rdpackages/rdhte
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rdhte-0.1.0-py3-none-any.whl -
Subject digest:
08f701b7c2f40c40290426828c13af7cbc370408b2ac24357387e0c63d3955a8 - Sigstore transparency entry: 1601886532
- Sigstore integration time:
-
Permalink:
rdpackages/rdhte@ba64a3aa16f91e68e7ac287f56f424db6705cac0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/rdpackages
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@ba64a3aa16f91e68e7ac287f56f424db6705cac0 -
Trigger Event:
workflow_dispatch
-
Statement type: