Metter. / Mixtapes / Methods Mixtape / Experimental Design

02 · Experimental Design

Pairwise Matching & Re-randomization

Two related strategies for improving covariate balance beyond stratified randomization: matched-pair designs that assign treatment and control within pairs of similar units, and re-randomization designs that repeatedly draw random assignments and accept only those meeting pre-specified balance criteria.


What it is

Pairwise matching and re-randomization are two approaches to achieving tighter covariate balance than stratified randomization alone. In a matched-pair design, units are ranked by a similarity metric (often the propensity score or a composite baseline index) and paired with their nearest neighbour. Within each pair, one unit is randomly assigned to treatment and the other to control. Because the two units in each pair are as similar as possible, the design minimises between-arm differences on the matching variable.

Re-randomization (Morgan & Rubin, 2012) draws many random assignments from the space of all possible assignments and accepts only those where the resulting treatment and control groups satisfy a pre-specified balance criterion (typically, a Mahalanobis distance or F-statistic from a balance test below a threshold). Accepted assignments are indistinguishable from each other; one is selected randomly from the accepted set.

Both designs increase precision by construction and are particularly valuable when sample sizes are small and chance imbalance is a genuine concern.

When to use it

Matched-pair designs are most useful when: (1) the sample is small (< 200 units); (2) one or a few baseline characteristics are strong predictors of the outcome; and (3) units can be convincingly matched on those characteristics before treatment assignment. They are common in cluster RCTs where the number of clusters is limited.

Re-randomization is more flexible than matching and does not require committing to a single matching variable or distance metric. It is well-suited to studies with several moderately predictive baseline covariates where no single matching dimension dominates.

How it works

Matched-pair design:

  1. Compute a similarity metric for all pairs of units (e.g., Mahalanobis distance on baseline covariates, or difference in propensity score).
  2. Greedily pair units: match the most similar two units, remove them from the pool, repeat until all units are paired (with an unpaired unit dropped if the sample is odd-sized).
  3. Within each pair, flip a fair coin to assign treatment.
  4. Analyse with pair fixed effects (each pair contributes one treated and one control observation; pair indicators are included in the regression).

Re-randomization:

  1. Specify a balance criterion in advance — e.g., the F-statistic from a joint test of baseline balance must be below a threshold corresponding to the 1% or 5% percentile of the F-distribution.
  2. Draw a random treatment assignment.
  3. Check whether it satisfies the balance criterion.
  4. If yes, accept; if no, discard and draw again.
  5. Repeat until an acceptable assignment is found.
  6. Analysis must account for the constrained randomization space (using randomization inference rather than standard t-tests, which assume an unrestricted randomization).

Key decisions

Matching variable selection. For pairwise matching, the matching variable(s) should be chosen on the basis of their correlation with the primary outcome, not their availability. Matching on a variable uncorrelated with the outcome does not improve precision. Matching on a variable with correlation r ≥ 0.5 with the outcome provides substantial efficiency gains.

Odd-size samples. When the sample size is odd, one unit will be unmatched. Options: drop the most dissimilar unit, form a triple (one treated, two controls), or use stratification for the unmatched unit. Document the choice.

Re-randomization acceptance rate. If the balance criterion is very tight, the acceptance rate for random assignments is low, requiring many draws. A criterion at the 1st percentile of the F-distribution accepts approximately 1% of random assignments. This is computationally trivial but analytically consequential: inference must use the constrained randomization distribution, not the standard normal or t-distribution.

Caveats & common mistakes

Not including pair/stratum fixed effects in analysis. Pair-matched designs require pair fixed effects in the regression. Without them, standard errors are overestimated (because the within-pair residuals are positively correlated). The design and analysis must be matched: pair fixed effects consume degrees of freedom equal to the number of pairs minus one, which can be costly in small samples.

Matching on post-enrollment variables. Matching must be done on pre-treatment baseline data. Attempting to improve balance post-enrollment by re-matching undermines the experimental design.

Using standard inference after re-randomization. Treating a re-randomized design as if it were a simple randomized design and applying standard t-tests or OLS standard errors is conservative but can lead to over-rejection when the balance criterion was strict. Randomisation inference (which respects the restricted randomization space) provides exact p-values. For large samples, the difference is small; for small samples, it matters.

Analysis Guide

import pandas as pd
import numpy as np
import statsmodels.formula.api as smf
from scipy.spatial.distance import cdist
from scipy.optimize import linear_sum_assignment
from scipy.stats import f as fdist

# 1. Optimal pairwise matching on baseline covariates — Mahalanobis distance is
#    scale-invariant and accounts for covariance among matching variables;
#    linear_sum_assignment finds the pairing that minimises total within-pair distance
np.random.seed(42)
covs = ["baseline_score", "age", "hh_size"]
X = df[covs].to_numpy()
VI = np.linalg.pinv(np.cov(X, rowvar=False))
D = cdist(X, X, metric="mahalanobis", VI=VI)
np.fill_diagonal(D, np.inf)

# 2. Greedy nearest-neighbour pairing — pop the closest pair, remove both, repeat;
#    this returns a stable pair assignment for an even-sized sample
pair_id = np.full(len(df), -1)
pid = 0
remaining = set(range(len(df)))
while len(remaining) >= 2:
  sub = list(remaining)
  sub_idx = np.array(sub)
  sub_D = D[np.ix_(sub_idx, sub_idx)]
  i, j = np.unravel_index(np.argmin(sub_D), sub_D.shape)
  a, b = sub_idx[i], sub_idx[j]
  pair_id[a] = pair_id[b] = pid; pid += 1
  remaining -= {a, b}
df["pair_id"] = pair_id

# 3. Assign treatment within each pair — one unit per pair drawn to treatment so
#    every pair contributes exactly one treated and one control observation
df["treatment"] = (df.groupby("pair_id").cumcount()
                   .eq(df.groupby("pair_id")["pair_id"].transform(
                       lambda s: np.random.randint(0, 2)))).astype(int)

# 4. Outcome regression with pair fixed effects — omitting C(pair_id) treats
#    within-pair correlation as noise and inflates standard errors, wasting the
#    precision gains the matched design was supposed to deliver
fit = smf.ols("outcome ~ treatment + C(pair_id)", data=df).fit(cov_type="HC1")
print(fit.params["treatment"], fit.bse["treatment"])

# 5. Re-randomisation loop: draw assignments, keep only those whose joint balance
#    F-statistic on baseline covariates is below the 5th percentile of the F dist;
#    this restricts the randomisation space to the most-balanced 5% of all draws
covs = ["age", "female", "hh_size", "log_expenditure"]
threshold = fdist.ppf(0.05, len(covs), len(df) - len(covs) - 1)
for it in range(10000):
  cand = np.random.binomial(1, 0.5, size=len(df))
  tmp = df.assign(treatment_try=cand)
  f_stat = smf.ols("treatment_try ~ " + " + ".join(covs), data=tmp).fit().fvalue
  if f_stat < threshold:
      df["treatment"] = cand
      print(f"Accepted after {it+1} iterations"); break

Reading the output

  • In the pair fixed effects regression, the treatment coefficient is the within-pair average treatment effect; the standard error will be smaller than an unstratified regression by approximately sqrt(1 − r²) where r is the within-pair correlation on the outcome.
  • Pairs where both units have the same treatment assignment indicate a pairing or coding error — each pair must have exactly one treated and one control unit.
  • For re-randomization, a low acceptance rate (< 1%) means the balance criterion is very strict; log the number of iterations to confirm the algorithm converged.
  • After re-randomization, standard t-tests are conservative; for small samples (N < 200), use randomisation inference to compute exact p-values that respect the constrained assignment space.

References

Morgan, K. L., & Rubin, D. B. (2012). Rerandomization to improve covariate balance in experiments. Annals of Statistics, 40(2), 1263–1282. https://doi.org/10.1214/12-AOS1008

Imai, K., King, G., & Nall, C. (2009). The essential role of pair matching in cluster-randomized experiments, with application to the Mexican Universal Health Insurance Evaluation. Statistical Science, 24(1), 29–53. https://doi.org/10.1214/08-STS274

Bruhn, M., & McKenzie, D. (2009). In pursuit of balance: Randomization in practice in development field experiments. American Economic Journal: Applied Economics, 1(4), 200–232. https://doi.org/10.1257/app.1.4.200

Li, X., & Ding, P. (2020). Rerandomization and regression adjustment. Journal of the Royal Statistical Society: Series B, 82(1), 241–268. https://doi.org/10.1111/rssb.12353

Last updated: 5 June 2026