Search code examples
rmetafor

metafor rma.mv: no convergence with random = list(~1 |id1, ~1 | id2) but with random = list(~ id1|id2)


I am using metafor package in R and very interestingly, I found for the same dataset, ~id1|id2 formula seems to give fewer "no convergence" results compared to list(~1|id1, ~1|id2). Could anyone explain the reason behind it? Thank you in advance!

Here is a test data to reproduce the issue:

# Case 1 - different results on convergence
df <- data.frame(bac = c("a","b","c"), id2 = c("A","B","B"), id1 = c("d","e","f"), ES = c(0.5603294, -1.8397608, -1.7491630), SE=c(2.368467, 1.240960, 1.287030))

rma.mv(yi=ES, V=(SE)^2,data=df,
       random = list( ~ id1|id2),
       control = list(maxiter = 500))

rma.mv(yi=ES, V=(SE)^2,data=df, random = list(~1|id1, ~1|id2), control = list(maxiter = 500))

# Case 2: exact the same results
df2 <- data.frame(id1= c("a","b","c","d"),id2=c("c1","c1","c2","c3"), Tech= c("a1","a2","a1","a1"),ES=c(-1.5,-3,1.5,3),SE=c(.2,.4,.2,.4))
rma.mv(ES, SE^2, random = ~ id1|id2, data=df2)
rma.mv(ES, SE^2, random = list(~ 1|id1,~ 1|id2), data=df2)

My session information

R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggplot2_3.2.1     matlib_0.9.2      magrittr_1.5      plyr_1.8.5        data.table_1.12.8
[6] metafor_2.1-0     Matrix_1.2-18     RNeo4j_1.7.0     

loaded via a namespace (and not attached):
 [1] rgl_0.100.50            Rcpp_1.0.3              lattice_0.20-38         assertthat_0.2.1       
 [5] digest_0.6.23           mime_0.9                R6_2.4.1                cellranger_1.1.0       
 [9] httr_1.4.1              pillar_1.4.3            rlang_0.4.4             lazyeval_0.2.2         
[13] curl_4.3                readxl_1.3.1            rstudioapi_0.10         miniUI_0.1.1.1         
[17] car_3.0-6               webshot_0.5.2           foreign_0.8-75          htmlwidgets_1.5.1      
[21] munsell_0.5.0           shiny_1.4.0             compiler_3.6.1          httpuv_1.5.2           
[25] xfun_0.12               pkgconfig_2.0.3         htmltools_0.4.0         tidyselect_1.0.0       
[29] tibble_2.1.3            rio_0.5.16              withr_2.1.2             crayon_1.3.4           
[33] dplyr_0.8.4             later_1.0.0             MASS_7.3-51.5           grid_3.6.1             
[37] nlme_3.1-143            jsonlite_1.6.1          xtable_1.8-4            gtable_0.3.0           
[41] lifecycle_0.1.0         scales_1.1.0            zip_2.0.4               stringi_1.4.5          
[45] carData_3.0-3           promises_1.1.0          vctrs_0.2.2             openxlsx_4.1.4         
[49] tools_3.6.1             forcats_0.4.0           manipulateWidget_0.10.1 glue_1.3.1             
[53] purrr_0.3.3             hms_0.5.3               crosstalk_1.0.0         abind_1.4-5            
[57] fastmap_1.0.1           colorspace_1.4-1        knitr_1.28              haven_2.2.0   

Solution

  • Fitting these models with such small datasets is rather pointless, but in general, there isn't any particular reason why it works in one case and not in the other. Achieving convergence, esp. with such small datasets, is difficult and may work better with one model specification versus the other. In the first case, you can get it to converge by switching optimizers; for example:

    rma.mv(yi=ES, V=(SE)^2, data=df, random = list(~1|id1, ~1|id2), control = list(optimizer="optim", optmethod="Nelder-Mead"))