This is based on R’s MatchIt and WeightIt packages and their documentations. All credits go to Noah Greifer and coauthors. I write to summarize what I have learned.
14.1 Assumptions
Matching or weighting is usually used in observational studies. We have the following assumptions before using matching or weighting to make a causal claim:
SUTVA
ignorability (unconfoundedness, or no unobserved confounders)
overlap (common support, or positivity)
With these assumptions, we can try to identify the treatment effect in an observational study.
14.2 Problem
The second assumption is saying controlling for \(X\), the treatment assignment \(D\) is independent of the potential outcomes \(Y(0)\) and \(Y(1)\), i.e., we have a pseudo-randomized experiment.
In reality, it’s rare we have a balanced distribution of \(X\) for treated and control. That’s when we need to use matching or weighting to balance the distribution of \(X\) between treatment and control groups.
14.3 weighting methods
The idea of weighting is to use weights to creat a pseudo population which has a balanced distribution of \(X\) for treated and control groups. The most popular weighting method is inverse probability of treatment weighting (IPTW). IPTW uses the propensity score to create weights.
There are a few other weighting methods that are gaining popularity.
14.3.1 Inverse probability of treatment weighting (IPTW)
IPTW is the most common weighting method. It uses the inverse of the propensity score as weights. The idea is to weight each treated unit by \(1/p\) and each control unit by \(1/(1-p)\), where \(p\) is the propensity score. This way, we can create a pseudo population where the distribution of \(X\) is balanced between treatment and control groups.
The same idea, but with a different way to estimate the propensity score. CBPS is a form of logistic regression where balance constraints are incorporated to a generalized method of moments estimation of the model coefficients.
14.3.3 Entropy balancing
Entropy balancing involves the specification of an optimization problem, the solution to which is then used to compute the weights. The constraints of the primal optimization problem correspond to covariate balance on the means (for binary and multi-category treatments) or treatment-covariate covariances (for continuous treatments), positivity of the weights, and that the weights sum to a certain value. Entropy balancing is doubly robust (for the ATT) in the sense that it is consistent either when the true propensity score model is a logistic regression of the treatment on the covariates or when the true outcome model for the control units is a linear regression of the outcome on the covariates, and it attains a semi-parametric efficiency bound when both are true. Entropy balancing will always yield exact mean balance on the included terms (not necessarily on the distribution of the covariates)
14.3.4 Energy balancing
Energy balancing is a method of estimating weights using optimization without a propensity score.
The primary benefit of energy balancing is that all features of the covariate distribution are balanced, not just means, as with other optimization-based methods like entropy balancing.
14.3.5 SuperLearner
SuperLearner works by fitting several machine learning models to the treatment and covariates and then taking a weighted combination of the generated predicted values to use as the propensity scores, which are then used to construct weights.
14.4 Example
Here is an example with Lalonde data, we are interested in the effect of treatment on “re78” (real earnings 1978).
14.4.1 IPW
library("WeightIt")library(cobalt)data(lalonde)w.out1<-weightit(treat~age+educ+race+married+nodegree+re74+re75, data =lalonde, estimand ="ATT", method ="glm")w.out1#print the output
A weightit object
- method: "glm" (propensity score weighting with GLM)
- number of obs.: 614
- sampling weights: none
- treatment: 2-category
- estimand: ATT (focal: 1)
- covariates: age, educ, race, married, nodegree, re74, re75
Balance Measures
Type Diff.Adj M.Threshold V.Ratio.Adj
age Contin. -0 Balanced, <0.05 0.4096
educ Contin. -0 Balanced, <0.05 0.6635
race_black Binary 0 Balanced, <0.05 .
race_hispan Binary 0 Balanced, <0.05 .
race_white Binary -0 Balanced, <0.05 .
married Binary -0 Balanced, <0.05 .
nodegree Binary 0 Balanced, <0.05 .
re74 Contin. -0 Balanced, <0.05 1.3265
re75 Contin. -0 Balanced, <0.05 1.3351
Balance tally for mean differences
count
Balanced, <0.05 9
Not Balanced, >0.05 0
Variable with the greatest mean difference
Variable Diff.Adj M.Threshold
re74 -0 Balanced, <0.05
Effective sample sizes
Control Treated
Unadjusted 429. 185
Adjusted 98.46 185
Suppose we are satisfied with the balance, we can use the weights to estimate the treatment effect. We can use the “marginaleffects” package to do that.
# Fit outcome modelfit<-lm_weightit(re78~treat*(age+educ+race+married+nodegree+re74+re75), data =lalonde, weightit =w.out2)# G-computation for the treatment effectlibrary("marginaleffects")avg_comparisons(fit, variables ="treat", newdata =subset(lalonde, treat==1))
Summary of weights
- Weight ranges:
Min Max
treated 0 |---------------------------| 14.041
control 0 |---------------------| 11.065
- Units with the 5 most extreme weights by group:
10 179 125 137 124
treated 5.984 6.23 6.758 13.202 14.041
537 553 573 420 608
control 5.499 6.404 6.599 8.274 11.065
- Weight statistics:
Coef of Var MAD Entropy # Zeros
treated 1.821 1.054 0.92 0
control 1.264 0.866 0.579 0
- Effective Sample Sizes:
Control Treated
Unweighted 429. 185.
Weighted 165.42 43.04
if(!is.null(w.out3)){fit<-lm_weightit(re78~treat*(age+educ+race+married+nodegree+re74+re75), data =lalonde, weightit =w.out3)# G-computation for the treatment effectavg_comparisons(fit, variables ="treat")}
Matching and weighting are popular in different fields. We used to say matching involves discarding data therefore changing the estimand, but now with full matching and other methods, matching can be done without losing data. We used to believe weighting can be unstable, as weights can be highly variable, but with CBPS, entropy balancing and energy balancing, weighting can perform much better.
So, in practice, we can try different methods, either matching or weighting, and see which one gives us better balance. Then use “marginaleffects” to get the treatment effect.
---title: "Matching and Weighting - Part 2: weighting"date: "2025-05-31"---This is based on R's MatchIt and WeightIt packages and their documentations. All credits go to Noah Greifer and coauthors. I write to summarize what I have learned.## AssumptionsMatching or weighting is usually used in observational studies. We have the following assumptions before using matching or weighting to make a causal claim:1. SUTVA2. ignorability (unconfoundedness, or no unobserved confounders)3. overlap (common support, or positivity)With these assumptions, we can try to identify the treatment effect in an observational study.## ProblemThe second assumption is saying controlling for $X$, the treatment assignment $D$ is independent of the potential outcomes $Y(0)$ and $Y(1)$, i.e., we have a pseudo-randomized experiment.In reality, it's rare we have a balanced distribution of $X$ for treated and control. That's when we need to use matching or weighting to balance the distribution of $X$ between treatment and control groups.## weighting methodsThe idea of weighting is to use weights to creat a pseudo population which has a balanced distribution of $X$ for treated and control groups. The most popular weighting method is inverse probability of treatment weighting (IPTW). IPTW uses the propensity score to create weights.There are a few other weighting methods that are gaining popularity.### Inverse probability of treatment weighting (IPTW)IPTW is the most common weighting method. It uses the inverse of the propensity score as weights. The idea is to weight each treated unit by $1/p$ and each control unit by $1/(1-p)$, where $p$ is the propensity score. This way, we can create a pseudo population where the distribution of $X$ is balanced between treatment and control groups.### Covariate balancing propensity score (CBPS)The same idea, but with a different way to estimate the propensity score. CBPS is a form of logistic regression where balance constraints are incorporated to a generalized method of moments estimation of the model coefficients.### Entropy balancingEntropy balancing involves the specification of an optimization problem, the solution to which is then used to compute the weights. The constraints of the primal optimization problem correspond to covariate balance on the means (for binary and multi-category treatments) or treatment-covariate covariances (for continuous treatments), positivity of the weights, and that the weights sum to a certain value. Entropy balancing is doubly robust (for the ATT) in the sense that it is consistent either when the true propensity score model is a logistic regression of the treatment on the covariates or when the true outcome model for the control units is a linear regression of the outcome on the covariates, and it attains a semi-parametric efficiency bound when both are true. Entropy balancing will always yield exact mean balance on the included terms (not necessarily on the distribution of the covariates)### Energy balancingEnergy balancing is a method of estimating weights using optimization without a propensity score.The primary benefit of energy balancing is that all features of the covariate distribution are balanced, not just means, as with other optimization-based methods like entropy balancing.### SuperLearnerSuperLearner works by fitting several machine learning models to the treatment and covariates and then taking a weighted combination of the generated predicted values to use as the propensity scores, which are then used to construct weights.## ExampleHere is an example with Lalonde data, we are interested in the effect of treatment on "re78" (real earnings 1978).### IPW```{r}#| include: truelibrary("WeightIt")library(cobalt)data(lalonde)w.out1 <-weightit(treat ~ age + educ + race + married + nodegree + re74 + re75,data = lalonde, estimand ="ATT", method ="glm")w.out1 #print the outputsummary(w.out1)``````{r}#| include: truelibrary(cobalt)bal.tab(w.out1, stats =c("m", "v"), thresholds =c(m = .05))```### entropy balancing```{r}#| include: truew.out2 <-weightit(treat ~ age + educ + race + married + nodegree + re74 + re75,data = lalonde, estimand ="ATT", method ="ebal")summary(w.out2)bal.tab(w.out2, stats =c("m", "v"), thresholds =c(m = .05))```Suppose we are satisfied with the balance, we can use the weights to estimate the treatment effect. We can use the "marginaleffects" package to do that.```{r}# Fit outcome modelfit <-lm_weightit(re78 ~ treat * (age + educ + race + married + nodegree + re74 + re75),data = lalonde, weightit = w.out2)# G-computation for the treatment effectlibrary("marginaleffects")avg_comparisons(fit, variables ="treat",newdata =subset(lalonde, treat ==1))```### energy balancing```{r}#| include: truew.out3 <-tryCatch(weightit(treat ~ age + educ + race + married + nodegree + re74 + re75, data = lalonde,method ="energy", estimand ="ATE"),error =function(e) { message("Energy balancing failed: ", e$message); NULL })if (!is.null(w.out3)) summary(w.out3)``````{r}#| include: trueif (!is.null(w.out3)) { fit <-lm_weightit(re78 ~ treat * (age + educ + race + married + nodegree + re74 + re75),data = lalonde, weightit = w.out3)# G-computation for the treatment effectavg_comparisons(fit, variables ="treat")}```## comparing matching and weightingMatching and weighting are popular in different fields. We used to say matching involves discarding data therefore changing the estimand, but now with full matching and other methods, matching can be done without losing data. We used to believe weighting can be unstable, as weights can be highly variable, but with CBPS, entropy balancing and energy balancing, weighting can perform much better.So, in practice, we can try different methods, either matching or weighting, and see which one gives us better balance. Then use "marginaleffects" to get the treatment effect.---<!-- see-also-footer -->*Systematic treatment: [R](https://xiangao.github.io/causal_econometrics_guide/matching.html) · [Julia](https://xiangao.github.io/causal_econometrics_julia/matching.html).*