Native optimal full matching (Rosenbaum 1991; Hansen 2004): every unit is
placed in a matched set of one treated unit and one or more controls, or one
control and one or more treated units, so that the total within-set
propensity-score distance is the smallest possible. It is computed exactly:
an unrestricted full match is a minimum-weight edge cover of the
treated-control distance graph, found here through a maximum-weight matching
(a rectangular assignment problem, solved by shortest augmenting paths). The
distance is the absolute difference of propensity scores from a logistic
regression on covariates (or ps), and the weights are those of
MatchIt::matchit(method = "full", estimand = "ATT"): 1 for treated units,
treated/control counts of the set for controls, each group rescaled to its
size. Cross-validated against MatchIt + optmatch in tests/cross (optmatch
solves on distances rounded to a tolerance, so its total is never below this
one). No MatchIt/optmatch at runtime.
Arguments
- data
Data frame.
- treatment
Binary treatment column name.
- covariates
Character vector of covariates.
- ps
Optional propensity scores, one per row of
data(or named by its row names); estimated by logistic regression whenNULL.- n_subclasses
Ignored (the number of matched sets is part of the optimum); kept for back-compatibility.
Value
A list of class morie_match_result: matched_data (every
matched row, with distance, weights and subclass columns),
match_pairs (the treated-control links of the sets, with their
distances) and details$total_distance.
References
Rosenbaum, P. R. (1991). A characterization of optimal designs for observational studies. JRSS B, 53(3), 597–610.
Hansen, B. B. (2004). Full matching in an observational study of coaching for the SAT. JASA, 99(467), 609–618.
Examples
set.seed(1)
df <- data.frame(y = rnorm(200), d = rbinom(200, 1, 0.4),
x1 = rnorm(200), x2 = rnorm(200))
fm <- morie_matching_full(df, "d", c("x1", "x2"))
fm$details$total_distance
#> [1] 0.3162015
head(fm$matched_data[, c("d", "subclass", "weights")])
#> d subclass weights
#> 1 1 1 1.0000000
#> 2 0 2 0.3247126
#> 3 1 3 1.0000000
#> 4 1 4 1.0000000
#> 5 1 5 1.0000000
#> 6 1 6 1.0000000
