match
Estimate causal treatment effects from observational data by matching treated and control units on propensity scores or covariates, reducing confounding bias.
Instructions
Propensity score and covariate matching for treatment effect estimation. Validation: certified evidence with scoped limitations. Known limitations: greedy nearest-neighbour matching without replacement is order-dependent: the m_order convention can differ across packages and materially moves the estimate (>5x spread on MatchIt::lalonde with Mahalanobis distance). m_order='data' and 'closest' reproduce MatchIt exactly; m_order='farthest' is StatsPAI's own dynamic rule and is not MatchIt-equivalent; bias_correction=True follows a different convention from Matching::Match's BiasAdjust: StatsPAI regresses on the full covariate vector with unweighted OLS over all controls, the reference regresses on the matching variables weighted by match counts, so bias-corrected estimates can differ from it by about 0.1%. The uncorrected estimate and its Abadie-Imbens standard error are exact. Cost: Builds the dense n_treated x n_control distance matrix via scipy cdist before selecting neighbours: memory is O(n_treated x n_control). Comfortable into the thousands per arm; use a caliper or coarser blocking beyond that. Assumptions: Unconfoundedness / CIA: Y(d) perp D | X; Overlap / common support: tr...
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ties | No | How equidistant controls are handled under matching with replacement. 'first' keeps the lowest-index one; 'all' pools them and splits the weight (the Matching::Match convention, which removes the row-order dependence). | first |
| detail | No | Payload depth: 'minimal' (~150 tokens) for sub-step calls where only the point estimate is needed; 'standard' (~1K tokens) for diagnostics + coefficient table; 'agent' (~2K tokens, default) adds violations / next_steps / suggested_functions so the LLM can plan its next call without another round-trip. | agent |
| method | No | Matching method. 'caliper' is not a method -- pass caliper= to any nearest-neighbour variant. | nearest |
| m_order | No | Order treated units are processed in for greedy matching without replacement. The result depends on it materially (>5x spread on lalonde with Mahalanobis distance). 'data' and 'closest' reproduce the MatchIt rules of the same name. | smallest_min_dist |
| outcome | Yes | Outcome variable column name or outcome array. | |
| as_handle | No | If true, cache the fitted result on the server and return result_id + result_uri alongside the JSON payload so a subsequent tools/call can chain without re-running. | |
| data_path | Yes | Absolute path or URL to a data file. Supported: .csv / .tsv / .txt (delimited), .parquet / .pq, .feather / .arrow, .xlsx / .xls, .dta (Stata), .json / .jsonl. Schemes: file://, s3://, gs://, https://. | |
| result_id | No | Optional handle to a previously-fitted result (returned by an earlier call when as_handle=true). Tools that operate on a fitted object accept this in place of re-supplying data_path + columns. | |
| se_method | No | Standard error. 'auto' resolves to 'abadie_imbens' for nearest-neighbour, 'psmatch2' for kernel / radius, 'bootstrap' for llr. 'abadie_imbens' is the sample-ATT conditional variance (Stata psmatch2 ai()) and the only option measured to be correctly sized (0.95-1.04x the sampling SD, coverage 0.905-0.956 over 36 designs x 1000 reps; see benchmarks/matching_se_coverage.py). 'abadie_imbens_pop' is the population-ATT variance Matching::Match reports; 'psmatch2' the analytic Stata SE (1.50-1.69x, too wide); 'ai' the simple matched-pair SE (0.56-0.91x, never reaches nominal coverage); 'bootstrap' resamples within arm and re-estimates the propensity score each draw. | auto |
| treatment | Yes | Treatment indicator, treatment variable, or treatment array. | |
| covariates | Yes | Covariate matrix, DataFrame, or column names. | |
| data_columns | No | Optional column projection. Parquet/Feather/Stata loaders honour this for fast partial reads. | |
| caliper_scale | No | Units of `caliper`: 'raw' on the distance scale (Stata psmatch2) or 'sd' in standard deviations of the propensity score (MatchIt std.caliper=TRUE). | raw |
| data_sample_n | No | Optional uniform random subsample size (seed=0, deterministic) — useful on huge panels. | |
| tie_tolerance | No | With ties='all', how close squared distances (scaled by the variance of the distance measure) must be to count as tied. 1e-5 reproduces Matching::Match's distance.tolerance default. | |
| bootstrap_reps | No | Replications for se_method='bootstrap' | |
| bootstrap_seed | No | Seed for the bootstrap resampler | |
| mahalanobis_cov | No | Covariance defining the Mahalanobis metric: 'pooled' within-group (Rubin 1980, MatchIt) or 'total' full-sample (pre-1.21 behaviour). | pooled |
| llr_stata_compat | No | method='llr' only: reproduce Stata psmatch2's SUBSTITUTE for LLR (lpoly-smoothed outcome + nearest-neighbour matching) rather than genuine local linear regression. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||