Skip to content

Release v0.2.0: Optimal Matching, Covariate Calipers & Subclass Inference

Choose a tag to compare

@jtuenner jtuenner released this 02 Mar 10:39
· 34 commits to main since this release

Release v0.2.0: Optimal Matching, Covariate Calipers & Subclass Inference

We are thrilled to announce a major update to pymatchit-causal! This release brings significant new matching algorithms, critical tools for downstream statistical inference, massive performance optimizations, and a visual overhaul of our diagnostic plots.

Thank you to the community for the excellent GitHub issues and feedback that drove this release.

🚀 New Features

  • Optimal Matching (method='optimal'): You can now perform globally optimal matching. Unlike greedy nearest-neighbor matching, optimal matching minimizes the total absolute distance across all matched pairs in the dataset, ensuring the best possible overall balance.
  • Covariate-Specific Calipers: The caliper argument now accepts a dictionary, allowing you to set strict, independent thresholds for specific variables alongside the propensity score. Example: caliper={'distance': 0.1, 'age': 2} ensures matches are within 0.1 standard deviations of the propensity score and strictly within 2 years of age.
  • Subclass Identifiers for Downstream Inference: The matched_data dataframe now automatically exports a subclass column. This assigns a unique integer ID to each matched pair or stratum, which is essential for calculating cluster-robust standard errors in your final effect estimation models (mirroring the behavior of the R MatchIt package).
  • Matching Order Control (m_order): Added the ability to dictate the sequence of greedy matching. You can now specify m_order="largest", "smallest", or "random".

⚡ Performance & Visual Upgrades

  • $O(N)$ Nearest Neighbor Matching: Completely refactored the underlying KD-Tree logic for Nearest Neighbor matching without replacement. The algorithm now fits the tree globally once (rather than per-unit), eliminating infinite hangs on large datasets and matching thousands of rows in milliseconds.
  • Publication-Ready "Nature-Style" Love Plots: The love_plot has received a massive visual upgrade. It now features a clean, minimalist aesthetic (no heavy gridlines, optimized data-ink ratio, and improved scatter rendering) specifically designed to look beautiful in high-impact scientific journals.

🐛 Bug Fixes & Stability

  • Categorical/String Variable Diagnostics: Fixed a critical bug where running .summary() or .plot() on formulas containing string variables would cause a TypeError. Categorical variables are now safely routed through Patsy to generate properly evaluated dummy matrices (e.g., race[T.Hispanic]).
  • Fractional Weight Variance: Fixed an issue in diagnostics.py that occasionally produced zero or negative variances when calculating weighted statistics for ratios > 1. It now uses the robust unbiased reliability weights variance formula.
  • Caliper Scaling: Fixed the caliper threshold calculation to properly scale based on the global standard deviation of the distance measure, preventing overly restrictive drops.
  • eCDF Guardrails: Added explicit data-type validation to ecdf_plot. Attempting to plot a categorical variable will now gracefully raise an informative TypeError instead of causing a cascading Seaborn crash.
  • NaN Detection: Added explicit, clean guardrails to catch missing values (NaNs) in covariates before they hit the formula parser, providing users with clear instructions to impute or drop missing data.
  • Pandas Int64 Casting: Fixed an issue where casting index columns to Pandas nullable integers would silently fail when exporting matches in wide format.

*** To upgrade:

pip install --upgrade pymatchit-causal