Generates balance statistics for output objects from Matching, optmatch, ebal, and designmatch.

# S3 method for Match
bal.tab(x, 
        formula = NULL,
        data = NULL,
        treat = NULL,
        covs = NULL,
        stats,
        int = FALSE,
        poly = 1,
        distance = NULL,
        addl = NULL,
        continuous,
        binary,
        s.d.denom,
        thresholds = NULL,
        weights = NULL,
        cluster = NULL,
        imp = NULL,
        pairwise = TRUE,
        s.weights = NULL,
        abs = FALSE,
        subset = NULL,
        quick = TRUE,
        ...)

Arguments

x

either a Match object (the output of a call to Matching::Match() or Matching::Matchby()), an optmatch object (the output of a call to optmatch::pairmatch() or optmatch::fullmatch()), an ebalance object (the output of a call to ebal::ebalance() or ebal::ebalance.trim()), or the output of a call to designmatch::bmatch() or related wrapper functions from the designmatch package.

formula

a formula with the treatment variable as the response and the covariates for which balance is to be assessed as the predictors. All named variables must be in data. See Details.

data

a data frame containing variables named in formula, if supplied, and other arguments.

treat

a vector of treatment statuses. See Details.

covs

a data frame of covariate values for which to check balance. See Details.

stats, int, poly, distance, addl, continuous, binary, thresholds, weights, cluster, imp, pairwise, s.weights, abs, subset, quick, ...

see bal.tab() for details.

See below for a special note on the s.d.denom argument.

The following argument has a special notes when used with these input objects:

s.d.denom

if not specified, for Match objects, bal.tab() will use "treated" if the estimand of the call to Match() is the ATT, "pooled" if the estimand is the ATE, and "control" if the estimand is the ATC; for optmatch, ebal, and designmatch objects, bal.tab() will determine which value makes the most sense based on the input. Abbreviations allowed.

Details

bal.tab() generates a list of balance summaries for the object given, and function similarly to Matching::MatchBalance() and designmatch::meantab(). Note that output objects from designmatch do not have their own class; bal.tab() first checks whether the object meets the criteria to be treated as a designmatch object before dispatching the correct method. Renaming or removing items from the output object can create unintended consequences.

The input to bal.tab.Match(), bal.tab.optmatch(), bal.tab.ebalance(), and bal.tab.designmatch() must include either both formula and data or both covs and treat. Using the formula + data inputs mirrors how Matching::MatchBalance() is used, and using the covs + treat input mirrors how designmatch::meantab() is used. (Note that to see identical results to meantab(), s.d.denom must be set to "pooled", though this is not recommended.) For optmatch output objects, specifying a treatment is not required.

Value

For point treatments, if clusters and imputations are not specified, an object of class "bal.tab" containing balance summaries for the given object. See bal.tab() for details.

If clusters are specified, an object of class "bal.tab.cluster" containing balance summaries within each cluster and a summary of balance across clusters. See bal.tab.cluster for details.

Author

Noah Greifer

See also

bal.tab() for details of calculations.

Examples

########## Matching ##########

library(Matching); data("lalonde", package = "cobalt")
#> ## 
#> ##  Matching (Version 4.10-2, Build Date: 2022-04-13)
#> ##  See http://sekhon.berkeley.edu/matching for additional documentation.
#> ##  Please cite software as:
#> ##   Jasjeet S. Sekhon. 2011. ``Multivariate and Propensity Score Matching
#> ##   Software with Automated Balance Optimization: The Matching package for R.''
#> ##   Journal of Statistical Software, 42(7): 1-52. 
#> ##

p.score <- glm(treat ~ age + educ + race + 
            married + nodegree + re74 + re75, 
            data = lalonde, family = "binomial")$fitted.values
Match.out <- Match(Tr = lalonde$treat, X = p.score)

## Using formula and data
bal.tab(Match.out, formula = treat ~ age + educ + race + 
        married + nodegree + re74 + re75, data = lalonde)
#> Balance Measures
#>                Type Diff.Adj
#> age         Contin.   0.2106
#> educ        Contin.   0.0201
#> race_black   Binary   0.0054
#> race_hispan  Binary  -0.0051
#> race_white   Binary  -0.0003
#> married      Binary   0.0661
#> nodegree     Binary  -0.0079
#> re74        Contin.  -0.0772
#> re75        Contin.  -0.0127
#> 
#> Sample sizes
#>                      Control Treated
#> All                   429.       185
#> Matched (ESS)          49.17     185
#> Matched (Unweighted)  136.       185
#> Unmatched             293.         0
########## optmatch ##########

library("optmatch"); data("lalonde", package = "cobalt")

lalonde$prop.score <- glm(treat ~ age + educ + race + 
            married + nodegree + re74 + re75, 
            data = lalonde, family = binomial)$fitted.values
pm <- pairmatch(treat ~ prop.score, data = lalonde)

## Using formula and data
bal.tab(pm, formula = treat ~ age + educ + race + 
        married + nodegree + re74 + re75, data = lalonde,
        distance = "prop.score")
#> Call
#>  pairmatch(x = treat ~ prop.score, data = lalonde)
#> 
#> Balance Measures
#>                 Type Diff.Adj
#> prop.score  Distance   0.9740
#> age          Contin.   0.0922
#> educ         Contin.  -0.1264
#> race_black    Binary   0.3730
#> race_hispan   Binary  -0.1568
#> race_white    Binary  -0.2162
#> married       Binary  -0.0162
#> nodegree      Binary   0.0703
#> re74         Contin.  -0.0539
#> re75         Contin.  -0.0247
#> 
#> Sample sizes
#>           Control Treated
#> All           429     185
#> Matched       185     185
#> Unmatched     244       0
########## ebal ##########

library("ebal"); data("lalonde", package = "cobalt")
#> ##
#> ## ebal Package: Implements Entropy Balancing.
#> ## See http://www.stanford.edu/~jhain/ for additional information.
#> 

covariates <- subset(lalonde, select = -c(re78, treat, race))
e.out <- ebalance(lalonde$treat, covariates)
#> Converged within tolerance 

## Using treat and covs
bal.tab(e.out, treat = lalonde$treat, covs = covariates)
#> Balance Measures
#>               Type Diff.Adj
#> age        Contin.       -0
#> educ       Contin.       -0
#> married     Binary       -0
#> nodegree    Binary        0
#> re74       Contin.       -0
#> re75       Contin.       -0
#> prop.score Contin.        0
#> 
#> Effective sample sizes
#>            Control Treated
#> Unadjusted  429.       185
#> Adjusted     95.28     185
########## designmatch ##########
# \donttest{
library("designmatch"); data("lalonde", package = "cobalt")
#> Loading required package: lattice
#> Loading required package: slam
#> Loading required package: Rglpk
#> Using the GLPK callable library version 5.0

covariates <- as.matrix(lalonde[c("age", "educ", "re74", "re75")])
treat <- lalonde$treat
dmout <- bmatch(treat,
                total_groups = sum(treat == 1),
                mom = list(covs = covariates,
                           tols = absstddif(covariates, 
                                            treat, .05))
                )
#>   Building the matching problem... 
#>   GLPK optimizer is open... 
#>   Finding the optimal matches... 
#>   Optimal matches found 

## Using treat and covs
bal.tab(dmout, treat = treat, covs = covariates)
#> Balance Measures
#>         Type Diff.Adj
#> age  Contin.   0.0567
#> educ Contin.  -0.0538
#> re74 Contin.  -0.0613
#> re75 Contin.  -0.0501
#> 
#> Sample sizes
#>           Control Treated
#> All           429     185
#> Matched       185     185
#> Unmatched     244       0
# }