Targeted Stable Balancing Weights Using Optimization

Use optimization to estimate weights that balance covariates for binary, multinomial, continuous, and longitudinal treatments in the spirit of Zubizarreta (2015) . The degree of balance can be specified for each covariate. In addition, sampling weights can be estimated that allow a sample to generalize to a population specified with given target moments of covariates.


CRAN_Status_Badge CRAN_Downloads_Badge

optweight contains functions to estimate weights that balance treatments to given balance thresholds. It solves a quadratic programming problem to minimize an objective function of the weights using solve_osqp() in the rosqp package. This is the method described in Zubizarreta (2015). optweight extends the method to multinomial, continuous, and longitudinal treatments and provides a simple user interface and compatibility with the cobalt package.

Below is an example of estimating weights with optweight and assessing balance on the covariates with cobalt.

devtools::install_github("ngreifer/optweight")  #development version
library("optweight")
library("cobalt")
data("lalonde")
 
# Estimate weights
ow <- optweight(treat ~ age + educ + race + nodegree + married + re74 + re75 + 
    I(re74 == 0) + I(re75 == 0), data = lalonde, estimand = "ATT", tols = 0.01)
ow
An optweight object
 - number of obs.: 614
 - sampling weights: none
 - treatment: 2-category
 - estimand: ATT (focal: 1)
 - covariates: age, educ, race, nodegree, married, re74, re75, I(re74 == 0), I(re75 == 0)
summary(ow)
Summary of weights:

- Weight ranges:
           Min                                  Max
treated 1.0000     ||                        1.0000
control 0.0021 |---------------------------| 7.4319

- Units with 5 greatest weights by group:
                                           
              2      3      4      5      6
 treated      1      1      1      1      1
            608    574    559    573    303
 control 7.2344 7.3161 7.4058 7.4058 7.4319

        Coef of Var Mean Abs Dev
treated      0.0000       0.0000
control      1.9018       1.3719
overall      1.5897       0.9585

- Effective Sample Sizes:
           Control Treated
Unweighted 429.000     185
Weighted    92.917     185
bal.tab(ow)
Call
 optweight(formula = treat ~ age + educ + race + nodegree + married + 
    re74 + re75 + I(re74 == 0) + I(re75 == 0), data = lalonde, 
    tols = 0.01, estimand = "ATT")

Balance Measures
                Type Diff.Adj
age          Contin.     0.01
educ         Contin.     0.01
race_black    Binary     0.01
race_hispan   Binary     0.00
race_white    Binary    -0.01
nodegree      Binary     0.01
married       Binary    -0.01
re74         Contin.     0.01
re75         Contin.     0.01
I(re74 == 0)  Binary     0.01
I(re75 == 0)  Binary     0.01

Effective sample sizes
           Control Treated
Unadjusted 429.000     185
Adjusted    92.917     185
# Estimate a treatment effect
library("jtools")
summ(lm(re78 ~ treat, data = lalonde, weights = ow$weights), confint = TRUE, 
    robust = TRUE, model.fit = FALSE)
MODEL INFO:
Observations: 614
Dependent Variable: re78
Type: OLS linear regression 

Standard errors: Robust, type = HC3
               Est.    2.5%   97.5% t val.    p    
(Intercept) 5342.94 4635.09 6050.78  14.85 0.00 ***
treat       1006.21   57.22 1955.19   2.09 0.04   *

The lower-level function optweight.fit operates on the covariates and treatment variables directly.

In addition to estimating balancing weights for estimating treatment effects, optweight can estimate sampling weights for generalizing an estimate to a new target population defined by covariate moments using the function optweight.svy.

News

optweight News and Updates

Version 0.2.2

  • Fixed bug with duals displaying improperly when factor variables are present.

Version 0.2.1

  • Changed default min.w in optweight.fit() and optweight.svy.fit() to 1E-8 from 0. This ensures all weights are nonzero, which can reduce bugs in other functions that require nonzero weights (e.g, summ() in jtools and svyglm() in survey`).

  • Fixed warning that would occur when interactions were present in the model formula in optweight().

  • optweights have been discovered to be invalid for longitudinal treatments, so attempting to use optweight()or optweight.fit() with longitudinal treatments will now produce an error. This can be overridden by setting force = TRUE, though this is not recommended until further research is done.

Version 0.2.0

  • Added optweight.svy and associated methods and functions for estimating survey weights using optimization. These weights when applied to the sample will yield a sample whose covariate means are equal (within a specified tolerance) to given target values.

  • Minor changes to check.targets. It will now produce the covariate means when the targets argument is empty and will produce the previous empty output, a named vector of NAs, when targets = NULL.

  • Changes to how dual variables are processed and displayed. Now, each dual variable coming from optweight represents the change in the objective function corresponding to a 1-unit change in tols. The reported duals are the sum of all the duals affected by the constraint, so you can now reliably predict the change in the objective function from a change in tols (it was obscured and error-prone previously). The distinction between targeting duals and balance duals is maintained.

Version 0.1.0

  • First version!

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("optweight")

0.2.2 by Noah Greifer, 4 months ago


Browse source code at https://github.com/cran/optweight


Authors: Noah Greifer [aut, cre]


Documentation:   PDF Manual  


GPL license


Imports rosqp, Matrix, ggplot2

Suggests cobalt, twang


Suggested by WeightIt, cobalt.


See at CRAN