paul-buerkner / brms

brms R package for Bayesian generalized multivariate non-linear multilevel models using Stan
https://paul-buerkner.github.io/brms/
GNU General Public License v2.0
1.27k stars 183 forks source link

Allow `brm_multiple()` to receive a `mild` object #1383

Closed ngreifer closed 2 years ago

ngreifer commented 2 years ago

The brm_multiple() documentation says that the data argument can be a list of data frames. After using complete() on a mids object resulting from mice(), the result is a mild object, which is nothing more than a list of data frames. However, brm_multiple() throws an error. Perhaps is_data_list() can be more tolerant of these kinds of objects, or use more robust checks that would allow for other forms of lists of data frames that happen to have an additional class. This is in reference to this post on SO. Thanks!

paul-buerkner commented 2 years ago

I agree. That should work. Could you perhaps provide a small reprex? Also, from which package does is_data_list come from?

ngreifer commented 2 years ago

Sure, reprex below.

data("lalonde_mis", package = "cobalt")
library(mice, warn.conflicts = FALSE)
library(brms, warn.conflicts = FALSE)
#> Loading required package: Rcpp
#> Loading 'brms' package (version 2.17.0). Useful instructions
#> can be found by typing help('brms'). A more detailed introduction
#> to the package is available through vignette('brms_overview').

imp <- mice(lalonde_mis, m = 3, printFlag = FALSE)
imp.data <- complete(imp, "all")
str(imp.data)
#> List of 3
#>  $ 1:'data.frame':   614 obs. of  9 variables:
#>   ..$ treat   : int [1:614] 1 1 1 1 1 1 1 1 1 1 ...
#>   ..$ age     : int [1:614] 37 22 30 27 33 22 23 32 22 33 ...
#>   ..$ educ    : int [1:614] 11 9 12 11 8 9 12 11 16 12 ...
#>   ..$ race    : Factor w/ 3 levels "black","hispan",..: 1 2 1 1 1 1 1 1 1 3 ...
#>   ..$ married : int [1:614] 1 0 0 0 0 0 0 0 0 1 ...
#>   ..$ nodegree: int [1:614] 1 1 0 1 1 1 0 1 0 0 ...
#>   ..$ re74    : num [1:614] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ re75    : num [1:614] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ re78    : num [1:614] 9930 3596 24909 7506 290 ...
#>  $ 2:'data.frame':   614 obs. of  9 variables:
#>   ..$ treat   : int [1:614] 1 1 1 1 1 1 1 1 1 1 ...
#>   ..$ age     : int [1:614] 37 22 30 27 33 22 23 32 22 33 ...
#>   ..$ educ    : int [1:614] 11 9 12 11 8 9 12 11 16 12 ...
#>   ..$ race    : Factor w/ 3 levels "black","hispan",..: 1 2 1 1 1 1 1 1 1 3 ...
#>   ..$ married : int [1:614] 1 0 0 0 0 0 0 0 0 1 ...
#>   ..$ nodegree: int [1:614] 1 1 0 1 1 1 0 1 0 0 ...
#>   ..$ re74    : num [1:614] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ re75    : num [1:614] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ re78    : num [1:614] 9930 3596 24909 7506 290 ...
#>  $ 3:'data.frame':   614 obs. of  9 variables:
#>   ..$ treat   : int [1:614] 1 1 1 1 1 1 1 1 1 1 ...
#>   ..$ age     : int [1:614] 37 22 30 27 33 22 23 32 22 33 ...
#>   ..$ educ    : int [1:614] 11 9 12 11 8 9 12 11 16 12 ...
#>   ..$ race    : Factor w/ 3 levels "black","hispan",..: 1 2 1 1 1 1 1 1 1 3 ...
#>   ..$ married : int [1:614] 1 0 0 0 0 0 0 0 0 1 ...
#>   ..$ nodegree: int [1:614] 1 1 0 1 1 1 0 1 0 0 ...
#>   ..$ re74    : num [1:614] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ re75    : num [1:614] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ re78    : num [1:614] 9930 3596 24909 7506 290 ...
#>  - attr(*, "class")= chr [1:2] "mild" "list"
class(imp.data)
#> [1] "mild" "list"

fit <- brm_multiple(re78 ~ treat,
                    data = imp.data)
#> Error: 'data' must be a list of data.frames.

Created on 2022-08-01 by the reprex package (v2.0.1)

is_data_list() is an internal function in brms that is the cause of the problem. It uses is.vector() to determine whether the input is acceptable, which returns FALSE for lists that happen to have an additional class or attribute. It should probably use something like

is.list(x) && all(vapply(x, is.data.frame, logical(1L)))

instead.

paul-buerkner commented 2 years ago

I see. Thank you! So far it has come that I don't remember my own function :-D

paul-buerkner commented 2 years ago

Fixed.