ngreifer / cobalt

Covariate Balance Tables and Plots - An R package for assessing covariate balance
https://ngreifer.github.io/cobalt/
72 stars 11 forks source link

Density plot using bal.plot() from CBPS object #31

Closed ariakhademi closed 4 years ago

ariakhademi commented 4 years ago

Thanks for providing the package cobalt. I'm trying to use it with the CBPS package, but I have a problem plotting. I can't get "bal.plot()" to generate density or histogram plots of the object generated by CBPS. Even if I specify the "type" and variable name properly, it returns a scatterplot. All of the examples provided online have tried objects generated by other packages such as MatchIt, but none with CBPS. However, other functions like love.plot() are working fine with CBPS. I was wondering if you've tried density plots for objects generated by CBPS?

ngreifer commented 4 years ago

H, thank you for bringing this up. Unfortunately I wasn't able to replicate this issue. Running the following always behaves as expected:

library(CBPS); library(cobalt)
#> Loading required package: MASS
#> Loading required package: MatchIt
#> Loading required package: nnet
#> Loading required package: numDeriv
#> Loading required package: glmnet
#> Loading required package: Matrix
#> Loading required package: foreach
#> Loaded glmnet 2.0-18
#> CBPS: Covariate Balancing Propensity Score
#> Version: 0.21
#> Authors: Christian Fong [aut, cre],
#>   Marc Ratkovic [aut],
#>   Kosuke Imai [aut],
#>   Chad Hazlett [ctb],
#>   Xiaolin Yang [ctb],
#>   Sida Peng [ctb]
#>  cobalt (Version 3.9.0, Build Date: 2019-10-06 19:10:02 UTC)
#>    Please read the documentation at ?bal.tab to understand the default outputs.
#>    Submit bug reports and feature requests to https://github.com/ngreifer/cobalt/issues
#>    Install the development version (not guaranteed to be stable) with:
#>      devtools::install_github("ngreifer/cobalt")
#>    Thank you for using cobalt!
#> 
#> Attaching package: 'cobalt'
#> The following object is masked from 'package:MatchIt':
#> 
#>     lalonde
data("lalonde", package = "cobalt")

#Binary (0, 1) treatment
out <- CBPS(treat ~ age + educ + married + race, data = lalonde, ATT = 1)
#> [1] "Finding ATT with T=1 as the treatment.  Set ATT=2 to find ATT with T=0 as the treatment"
bal.plot(out, "age")


out <- CBPS(treat ~ age + educ + married + race, data = lalonde, ATT = 0)
bal.plot(out, "age")


#Factor treatment
out <- CBPS(race ~ age + educ + married + nodegree, data = lalonde)
bal.plot(out, "age")


#Binary (1, 2) treatment; CBPS treats as continuous,
#bal.plot correctly interprets as binary
lalonde$treat2 <- lalonde$treat + 1
out <- CBPS(treat2 ~ age + educ + married + race, data = lalonde, method = "exact")
#> Warning in CBPS.fit(X = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, :
#> Treatment vector is numeric. Interpreting as a continuous treatment. To
#> solve for a binary or multi-valued treatment, make treat a factor.
bal.plot(out, "age")

Created on 2019-12-17 by the reprex package (v0.3.0)

Can you provide me with a reproducible example? Also, if this is causing you issues, you should try doing the same analysis using WeightIt, which performs CBPS too, using the same syntax.

istallworthy commented 1 year ago

I too seem to be having issues with bal.tab and other functions from cobalt accepting CBPS output (binary treatment). i keep getting "Error: 'f' must be a formula'. Any thoughts here? Thanks in advance for this package and any advice!

ngreifer commented 1 year ago

@istallworthy So sorry you're having this issue! Are you using the most recent version of cobalt? Can you tell me what other packages you have loaded when you run into this issue (this is almost certainly what the problem is)?

istallworthy commented 1 year ago

thanks for your quick reply! i did just install cobalt the same day so i believe it is the most recent version (4.4.1?) of the package. in addition to cobalt and cbps, i also have the following packages loaded: dplyr, devtools, datasets, ggplot2, graphics, grDevices, methods, purrr, readr, stats, stringr, tableHTML, testthat, tidyr, tidyverse, usethis, and utils. thanks!

ngreifer commented 1 year ago

Unforutnately I cannot reproduce your error:

library(cobalt)
#>  cobalt (Version 4.4.1, Build Date: 2022-11-03)
library(CBPS)
for (i in c("dplyr", "devtools", "datasets", "ggplot2", "graphics", "grDevices", 
            "methods", "purrr", "readr", "stats", "stringr", "tableHTML", 
            "testthat", "tidyr", "tidyverse", "usethis"))
  library(i, character.only = T)

data("lalonde")
m <- CBPS(factor(treat) ~ age + educ + married + race + re74, data = lalonde)
#> [1] "Finding ATT with T=1 as the treatment.  Set ATT=2 to find ATT with T=0 as the treatment"
bal.tab(m)
#> Balance Measures
#>                 Type Diff.Adj
#> prop.score  Distance  -0.0201
#> age          Contin.  -0.0038
#> educ         Contin.   0.0009
#> married       Binary  -0.0006
#> race_black    Binary   0.0004
#> race_hispan   Binary  -0.0000
#> race_white    Binary  -0.0004
#> re74         Contin.  -0.0004
#> 
#> Effective sample sizes
#>            Control Treated
#> Unadjusted  429.       185
#> Adjusted    105.46     185
bal.plot(m, "age", which = "both")
#> Warning: The following aesthetics were dropped during statistical transformation: weight
#> ℹ This can happen when ggplot fails to infer the correct grouping structure in
#>   the data.
#> ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
#>   variable into a factor?

love.plot(m)
#> Warning: Standardized mean differences and raw mean differences are present in the same plot. 
#> Use the 'stars' argument to distinguish between them and appropriately label the x-axis.

Created on 2022-12-09 with reprex v2.0.2

Can you give me a minimal reproducible example or at least show me what code you're using?

istallworthy commented 1 year ago

the code i'm using is as follows, in case this helps:

form="INR_bin ~ BrestFed + BSI.6 + ESETA1.6 + HOMEETA1.6 + HomeOwnd + HrsOfTV + IBQDnovm + Infectin + KFastScr + Med_6_R + NC + NumHH2_R + PCX_NEG.6 + PCX_POS.6 + PEmply2 + PPJWHr2_R + PregOTC + RcvErlHS + RcvFodSt + RcvGvCC + RcvGvHC + RcvGvHou + RcvGvTrn + RcvSchFd + RcvWIC + RGotAFDC + RGotFodS + RGotPubH + RHasSO + RHealth + RMAge1st + RMarStat + RMomAgeU + SurpPreg + TcBlac2 + WghtLoss + WIND.6"

fit <- CBPS::CBPS(form, data=MSMDATA_temp, ATT=0, iterations = 1000, standardize = TRUE, method = "exact", twostep = FALSE, sample.weights = NULL, baseline.formula = NULL, diff.formula = NULL) cobalt::bal.tab(fit)

Error: 'f' must be a formula.

I also tried again with the simplified

fit<-CBPS::CBPS(form,data=MSMDATA_temp)

and i get the same error.

thanks again!

ngreifer commented 1 year ago

I see. Could you try loading cobalt with library() instead of just using ::? This is a problem I've had that I need to work on, but doing this can sometimes solve it.

istallworthy commented 1 year ago

i tried loading cobalt with library() before and after running CBPS and running just bal.tab() with :: but I'm still getting the same error. I do appreciate the ideas, though!

ngreifer commented 1 year ago

I just had a thought. Don't include quotes around your formula. It's unnecessary and is probably why cobalt doesn't think the formula is actually a formula. You should never supply formulas as a string and the fact that CBPS accepts this is a convenience for the user but leads to weird issues like this when formula inputs are required.

istallworthy commented 1 year ago

That worked, thank you! and thanks for the tip about forms. i really appreciate it and will be sure to change that. (side note: you are still correct in that it does require me to manually load the cobalt library and doesn't like when i use ::).

ngreifer commented 1 year ago

Glad that solved it, still concerned about :: not working.

istallworthy commented 1 year ago

i don't know if this helps but this is the error i get when I remove the cobalt library and try to run cobalt::love.plot(fit):

Error in bal.tab(x = list(coefficients = c(0.882209404965283, -0.276814528516487, : could not find function "bal.tab"

The code runs if I pre-load the cobalt library manually.

ngreifer commented 1 year ago

That is helpful! I just made an edit to the GitHub version to address this, I would really appreciate it if you could test it out for me. You can install it using

remotes::install_github("ngreifer/cobalt")

Thanks!

istallworthy commented 1 year ago

definitely! when i do that, i now get the following error when i try to run love.plot() after manually loading the library or cobalt::love.plot():

Error: (converted from warning) Unadjusted values are missing. This can occur when un = FALSE and quick = TRUE in the original call to bal.tab().