View source: R/matching_core.R
| match_couples | R Documentation |
Performs one-to-one matching between two datasets. Supports blocking, distance constraints, and various distance metrics.
match_couples(
left,
right = NULL,
vars = NULL,
left_id = NULL,
right_id = NULL,
distance = "euclidean",
weights = NULL,
scale = FALSE,
auto_scale = FALSE,
max_distance = Inf,
calipers = NULL,
block_id = NULL,
ignore_blocks = FALSE,
require_full_matching = FALSE,
method = "auto",
strategy = c("row_best", "sorted", "pq"),
return_unmatched = TRUE,
return_diagnostics = FALSE,
parallel = FALSE,
replace = FALSE,
ratio = 1L,
check_costs = TRUE,
sigma = NULL,
memory_mode = "auto",
certify = NULL
)
left |
Data frame of "left" units (e.g., treated, cases) |
right |
Data frame of "right" units (e.g., control, controls) |
vars |
Variable names to use for distance computation |
left_id, right_id |
Name of the column holding the unit identifier, or
NULL (default) to use a column called |
distance |
Distance metric: "euclidean", "manhattan", "mahalanobis", or a custom function |
weights |
Optional named vector of variable weights |
scale |
Scaling method: FALSE (none), "standardize", "range", or "robust" |
auto_scale |
If TRUE, automatically check variable health and select scaling method (default: FALSE) |
max_distance |
Maximum allowed distance (pairs exceeding this are forbidden) |
calipers |
Named list of per-variable maximum absolute differences |
block_id |
Column name containing block IDs (for stratified matching) |
ignore_blocks |
If TRUE, ignore block_id even if present |
require_full_matching |
If TRUE, error if any units remain unmatched |
method |
Matching method. A LAP solver for optimal matching ("auto",
"hungarian", "jv", "gabow_tarjan", ...), or "greedy" for fast approximate
matching (see |
strategy |
Greedy strategy, used only when
|
return_unmatched |
Include unmatched units in output |
return_diagnostics |
Include detailed diagnostics in output |
parallel |
Enable parallel processing for blocked matching. Requires 'future' and 'future.apply' packages. Can be:
|
replace |
If TRUE, allow matching with replacement (same right unit can be matched to multiple left units). Default: FALSE. |
ratio |
Integer, number of right units to match per left unit. Default: 1 (one-to-one matching). For k:1 matching, set ratio = k. |
check_costs |
If TRUE, check distance distribution for potential problems and provide helpful warnings before matching (default: TRUE) |
sigma |
Optional covariance matrix for Mahalanobis distance. If NULL
(default), the pooled sample covariance is used. Only relevant when
|
memory_mode |
One of "auto" (default), "dense", "lazy" or "implicit".
"auto" warns (or, when |
certify |
Logical; whether the result carries a checked
|
With method set to a LAP solver (the default "auto", or "jv",
"hungarian", ...) it finds the matching that minimizes total distance among
all feasible matchings. With method = "greedy" it uses a fast greedy
strategy (selected by strategy) that does not guarantee the optimal total
distance but scales to very large datasets.
A list with class "matching_result" containing:
pairs: Tibble of matched pairs with distances
unmatched: List of unmatched left and right IDs
info: Matching diagnostics and metadata
status: One of solver_status_values(), computed from what the solve
achieved. "optimal" when every left unit found a partner under an
optimal method, "partial" when constraints left some unmatched,
"heuristic" when a greedy method ran, either because it was asked for
or because the constrained path fell back to it, and "infeasible" when
nothing could be matched.
Under memory_mode = "implicit" it also carries certificate, the checked
statement of optimality (see verify_assignment(), which names the
arithmetic it was decided in), and search: the pairs
the loop generated out of the pairs the problem states, the pairs a cost
was computed for, and one row per round of what each round did. An
infeasible answer carries witness instead, naming the units that could
not be matched and the partners they have between them.
# Basic matching
left <- data.frame(id = 1:5, x = c(1, 2, 3, 4, 5), y = c(2, 4, 6, 8, 10))
right <- data.frame(id = 6:10, x = c(1.1, 2.2, 3.1, 4.2, 5.1), y = c(2.1, 4.1, 6.2, 8.1, 10.1))
result <- match_couples(left, right, vars = c("x", "y"))
print(result$pairs)
# With constraints
result <- match_couples(left, right, vars = c("x", "y"),
max_distance = 1,
calipers = list(x = 0.5))
# With blocking
left$region <- c("A", "A", "B", "B", "B")
right$region <- c("A", "A", "B", "B", "B")
blocks <- matchmaker(left, right, block_type = "group", block_by = "region")
result <- match_couples(blocks$left, blocks$right, vars = c("x", "y"))
# Fast greedy matching for large datasets
result <- match_couples(left, right, vars = c("x", "y"),
method = "greedy", strategy = "sorted")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.