PairMatch#
PairMatch implements randomization inference for matched pairs with binary outcomes, following Wilson’s “Randomization Inference for Matched Pairs with Binary Outcomes” [Wil26]. Given pairs in which one treated unit is matched to one control and each unit’s outcome is 0 or 1, it produces exact confidence sets for the treatment effect and reports how much unmeasured confounding the finding withstands. It assumes nothing beyond the within-pair coin flip: it does not assume the treatment effect is monotonic, and it fits no outcome model.
The library provides:
Attributable effects: exact prediction sets for the net number of successes treatment caused among the treated (
A_1) or the untreated (A_0)Average treatment effects: ATT, ATU, and ATE confidence sets, combining
A_1andA_0via the Bonferroni proposition of Rigdon and Hudgens [RH15]Worst-case p-values from a closed-form worst-case allocation of effects, with no integer program and no numerical search
Sensitivity analysis under Rosenbaum’s \(\Gamma\)-model: the sensitivity value \(\Gamma^\bullet\), expanded confidence intervals, and the design sensitivity \(\tilde{\Gamma}\)
Combinations of net effects, including difference-in-differences, on the same matched pairs
Install it from PyPI with pip install PairMatch (or uv add
PairMatch). The distribution is named PairMatch; the import
package is pair_match.
Quickstart#
Everything starts from the four counts of outcome patterns among the
pairs. The first subscript is the treated unit’s outcome, the second the
control’s, so s10 counts pairs in which the treated unit succeeded
and its control did not. Build a
PairedOutcomeTable from the counts (or
from two aligned 0/1 outcome vectors with
from_outcomes()), then
call analyze():
from pair_match import PairedOutcomeTable
# The running example of [Wil26]: 1,000 pairs.
table = PairedOutcomeTable(s00=800, s01=30, s10=70, s11=100)
print(table.analyze(alpha=0.10, target="ATE"))
| ATE | Conf Int** | iSuccesses | Conf Int** | p-Value* | Γ• |
|--------+----------------+--------------+--------------+------------+---------|
| +4.00% | +0.55%, +7.45% | +40 | +6, +74 | 0.0484* | 1.03459 |
The last column is the sensitivity value: the largest hidden-bias odds ratio at which the finding still holds. Here it is barely above 1, so even slight unmeasured confounding could explain the effect. The Reproducing the Paper guide derives every number in this table, and every other calculation in [Wil26], step by step.
The full usage guide ships with the package and is available at runtime
through pair_match.usage(). Full citations are on the
References page.