Ursachen für bimodale Verteilungen beim Bootstrapping eines Metaanalysemodells

8

Ich helfe einem Kollegen, ein Metaanalyse-Modell mit gemischten Effekten mithilfe des von @Wolfgang verfassten Metafor R-Paket-Frameworks zu booten.

Interessanterweise und besorgniserregend erhalte ich für einen der Koeffizienten des Modells beim Bootstrapping eine bimodale Verteilung (siehe unten rechts in der Abbildung unten).

Ich denke, eine der Hauptursachen könnte die Tatsache sein, dass beim Bootstrapping beispielsweise die Hälfte der Modelle in einer lokalen Lösung und die andere Hälfte in einer anderen konvergiert. Ich habe versucht, den Konvergenzalgorithmus wie in dieser Metafor-Dokumentation vorgeschlagen zu optimieren - Konvergenzprobleme mit der Funktion rma () . Ich habe auch andere Konvergenzalgorithmen wie bobyqaund newuoawie in der Hilfedokumentation der Funktion rma.mv vorgeschlagen ausprobiert , aber die gleiche bimodale Antwort erhalten.

Ich habe auch versucht, einige der potenziellen Ausreißer aus der problematischen Gruppe zu entfernen, wie unter Interpretieren der multimodalen Verteilung der Bootstrap-Korrelation vorgeschlagen , aber ohne Erfolg.

Ich konnte keinen Weg finden, dies zu reproduzieren, als die Faktorstufen der Daten zu ändern und sie auf GitHub hochzuladen (die folgenden Links sollten in Ihrer Umgebung alles laden, was zum Testen des Falls erforderlich ist). Ich führe das Bootstrapping auf einem Linux-Cluster als Array-Job aus (nur für den Fall, dass das Shell-Skript job.sh ist , das auf jeder CPU das R-Skript bootstrap.r ausführt , das das unten beschriebene Modell ausführt ). Ein einzelner Lauf dauert 2-3 Minuten. Beachten Sie, dass ein 100-maliges Bootstrapping auch ausreicht, um die bimodale Reaktion zu erkennen. Unten finden Sie ein Beispiel für 1000 Iterationen. Ich bin mit R und anderen Methoden vertraut, aber nicht so sehr mit Metaanalysen.

Ich würde mich über Hilfe beim Verständnis freuen, wenn die bimodale Verteilung in Ordnung ist (obwohl dies möglicherweise auf Konvergenzprobleme zurückzuführen ist), und wenn nicht, was kann man dann dagegen tun? (außer was ich schon versucht habe)

Unten - Vergleich der Koeffizienten aus dem Bootstrapping (rote Linien) und aus einem einzelnen vollständigen Modelllauf (blaue Linien). Die Histogramme zeigen die Bootstrap-Verteilungen für jeden Koeffizienten. Das Abtasten der Daten für das Bootstrapping wurde als Auswahl mit Ersetzung aus jeder Gruppe / Kombination durchgeführt, die durch die zwei festen Effekte gebildet wurde. Ihre Rohprobengrößen sind:

table(dt$f1, dt$f2)
#>       
#>        f2_1 f2_2 f2_3
#>   f1_1  177  174   41
#>   f1_2  359  363  107
library(data.table)
library(ggplot2)
library(metafor)
#> Loading required package: Matrix
#> Loading 'metafor' package (version 2.0-0). For an overview 
#> and introduction to the package please type: help(metafor).

load(url("https://github.com/valentinitnelav/test/raw/master/bimodal_distrib_boot/coef_boot_dt_1010.rda"))
load(url("https://github.com/valentinitnelav/test/raw/master/bimodal_distrib_boot/rmamv_model.rda"))
load(url("https://github.com/valentinitnelav/test/raw/master/bimodal_distrib_boot/data.rda"))

coef_dt <- data.frame(estim = rmamv_model[["beta"]])
coef_dt$coef_name <- rownames(coef_dt)
coef_dt <- rbind(coef_dt,
                 coef_boot_dt[, .(estim = mean(coef)), by = coef_name])
coef_dt[, gr := rep(c("estim_model", "estim_boot"), each = 6)]

ggplot(data = coef_boot_dt,
       aes(x = coef,
           group = coef_name)) +
  geom_histogram(bins = 100) +
  geom_vline(aes(xintercept = estim,
                 group = gr,
                 color = gr),
             lwd = 1,
             data = coef_dt) +
  facet_wrap(vars(coef_name), ncol = 2)

Erstellt am 2019-05-02 vom reprex-Paket (v0.2.1)

Das Modell geht so:

rmamv_model <- rma.mv(y ~ f2:f1 - 1,
                  V = var_y,
                  random = list(~ 1|r1,
                                ~ 1|r2),
                  R = list(r2 = cor_mat),
                  data = dt,
                  method = "REML",
                  # Tune the convergence algorithm / optimizer
                  control = list(optimizer = "nlminb",
                                 iter.max = 1000,
                                 step.min = 0.4,
                                 step.max = 0.5))

R Sitzungsinfo:

devtools::session_info()
#> - Session info ----------------------------------------------------------
#>  setting  value                       
#>  version  R version 3.5.2 (2018-12-20)
#>  os       Windows 7 x64 SP 1          
#>  system   x86_64, mingw32             
#>  ui       RTerm                       
#>  language (EN)                        
#>  collate  English_United States.1252  
#>  ctype    English_United States.1252               
#>  date     2019-05-02                  
#> 
#> - Packages --------------------------------------------------------------
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 3.5.2)
#>  backports     1.1.3   2018-12-14 [1] CRAN (R 3.5.2)
#>  callr         3.2.0   2019-03-15 [1] CRAN (R 3.5.3)
#>  cli           1.1.0   2019-03-19 [1] CRAN (R 3.5.3)
#>  colorspace    1.4-1   2019-03-18 [1] CRAN (R 3.5.3)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 3.5.1)
#>  curl          3.3     2019-01-10 [1] CRAN (R 3.5.2)
#>  data.table  * 1.12.0  2019-01-13 [1] CRAN (R 3.5.2)
#>  desc          1.2.0   2018-05-01 [1] CRAN (R 3.5.1)
#>  devtools      2.0.1   2018-10-26 [1] CRAN (R 3.5.1)
#>  digest        0.6.18  2018-10-10 [1] CRAN (R 3.5.1)
#>  dplyr         0.8.0.1 2019-02-15 [1] CRAN (R 3.5.2)
#>  evaluate      0.13    2019-02-12 [1] CRAN (R 3.5.2)
#>  fs            1.2.7   2019-03-19 [1] CRAN (R 3.5.3)
#>  ggplot2     * 3.1.0   2018-10-25 [1] CRAN (R 3.5.1)
#>  glue          1.3.1   2019-03-12 [1] CRAN (R 3.5.2)
#>  gtable        0.2.0   2016-02-26 [1] CRAN (R 3.5.1)
#>  highr         0.8     2019-03-20 [1] CRAN (R 3.5.3)
#>  htmltools     0.3.6   2017-04-28 [1] CRAN (R 3.5.1)
#>  httr          1.4.0   2018-12-11 [1] CRAN (R 3.5.2)
#>  knitr         1.22    2019-03-08 [1] CRAN (R 3.5.2)
#>  labeling      0.3     2014-08-23 [1] CRAN (R 3.5.0)
#>  lattice       0.20-38 2018-11-04 [2] CRAN (R 3.5.2)
#>  lazyeval      0.2.2   2019-03-15 [1] CRAN (R 3.5.3)
#>  magrittr      1.5     2014-11-22 [1] CRAN (R 3.5.1)
#>  Matrix      * 1.2-15  2018-11-01 [2] CRAN (R 3.5.2)
#>  memoise       1.1.0   2017-04-21 [1] CRAN (R 3.5.1)
#>  metafor     * 2.0-0   2017-06-22 [1] CRAN (R 3.5.2)
#>  mime          0.6     2018-10-05 [1] CRAN (R 3.5.1)
#>  munsell       0.5.0   2018-06-12 [1] CRAN (R 3.5.1)
#>  nlme          3.1-137 2018-04-07 [2] CRAN (R 3.5.2)
#>  pillar        1.3.1   2018-12-15 [1] CRAN (R 3.5.2)
#>  pkgbuild      1.0.3   2019-03-20 [1] CRAN (R 3.5.3)
#>  pkgconfig     2.0.2   2018-08-16 [1] CRAN (R 3.5.1)
#>  pkgload       1.0.2   2018-10-29 [1] CRAN (R 3.5.1)
#>  plyr          1.8.4   2016-06-08 [1] CRAN (R 3.5.1)
#>  prettyunits   1.0.2   2015-07-13 [1] CRAN (R 3.5.1)
#>  processx      3.3.0   2019-03-10 [1] CRAN (R 3.5.3)
#>  ps            1.3.0   2018-12-21 [1] CRAN (R 3.5.2)
#>  purrr         0.3.2   2019-03-15 [1] CRAN (R 3.5.3)
#>  R6            2.4.0   2019-02-14 [1] CRAN (R 3.5.2)
#>  Rcpp          1.0.1   2019-03-17 [1] CRAN (R 3.5.3)
#>  remotes       2.0.2   2018-10-30 [1] CRAN (R 3.5.1)
#>  rlang         0.3.4   2019-04-07 [1] CRAN (R 3.5.3)
#>  rmarkdown     1.12    2019-03-14 [1] CRAN (R 3.5.3)
#>  rprojroot     1.3-2   2018-01-03 [1] CRAN (R 3.5.1)
#>  scales        1.0.0   2018-08-09 [1] CRAN (R 3.5.1)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 3.5.1)
#>  stringi       1.4.3   2019-03-12 [1] CRAN (R 3.5.2)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 3.5.1)
#>  tibble        2.1.1   2019-03-16 [1] CRAN (R 3.5.3)
#>  tidyselect    0.2.5   2018-10-11 [1] CRAN (R 3.5.1)
#>  usethis       1.4.0   2018-08-14 [1] CRAN (R 3.5.1)
#>  withr         2.1.2   2018-03-15 [1] CRAN (R 3.5.1)
#>  xfun          0.5     2019-02-20 [1] CRAN (R 3.5.2)
#>  xml2          1.2.0   2018-01-24 [1] CRAN (R 3.5.1)
#>  yaml          2.2.0   2018-07-25 [1] CRAN (R 3.5.1)
Valentin
quelle

Antworten:

6

Vielen Dank für die Bereitstellung der Daten und des Codes. Ich habe das Modell, mit dem Sie arbeiten, neu angepasst und die zweite Varianzkomponente (für die cor_matangegeben ist) driftet auf einen wirklich großen Wert ab, was seltsam ist. Das Profilieren dieser Varianzkomponente (mit profile(rmamv_model, sigma2=2)) weist jedoch auf keine Probleme hin, sodass ich nicht denke, dass dies ein Konvergenzproblem ist. Stattdessen denke ich, dass das Problem dadurch entsteht, dass das Modell keinen zufälligen Effekt auf Schätzungsebene enthält (den grundsätzlich jedes metaanalytische Modell enthalten sollte). Also würde ich vorschlagen zu passen:

dt$id <- 1:nrow(dt)

res <- rma.mv(y ~ f2:f1 - 1,
              V = var_y,
              random = list(~ 1|r1,
                            ~ 1|r2, 
                            ~ 1|id),
              R = list(r2 = cor_mat),
              data = dt,
              method = "REML")

Die Ergebnisse sehen viel vernünftiger aus. Ich vermute, dies könnte auch das Problem mit der bimodalen Bootstrap-Verteilung dieses letzten Koeffizienten lösen.

Wolfgang
quelle
1
Danke @Wolfgang! Es hat das Problem behoben! Die Koeffizienten sehen jetzt viel vernünftiger aus (sie entsprechen den Erwartungen / der Theorie) und es wurde auch das Problem der bimodalen Verteilung gelöst. Da Sie mit solchen Problemen sehr vertraut sind und sie zur Hand haben, wäre es wunderbar, wenn Sie auch einige von Experten begutachtete Referenzen bereitstellen könnten, die die Idee unterstützen, einen zufälligen Effekt auf Beobachtungsebene zu integrieren. Ich habe Harrison, 2014 , gefunden, scheint aber speziell für Zähldaten zu sein. Nochmals vielen Dank!
Valentin
Ich kenne keine Referenz, die dies wörtlich sagt, aber vielleicht möchten Sie einen Blick darauf werfen: metafor-project.org/doku.php/…
Wolfgang
1

Ohne Zugriff auf ein reproduzierbares Beispiel ist es äußerst schwierig, eine eindeutige Antwort auf dieses Bootstrapping-Verhalten zu geben. Unter der Annahme, dass es tatsächlich keine Ausreißer gibt, vermute ich, dass wir einen milden Fall von Steins Phänomen beobachten, insbesondere weil eine Methode mit gemischten Effekten darauf hindeutet, dass sich unsere Daten etwas gruppieren.

Vor diesem Hintergrund würde ich vorschlagen, einige der Läufe f2f2_3:f1f1_2anhand der "ungewöhnlichen" Werte der Interaktion zu betrachten, bei denen es sehr unterschiedliche Werte gibt, und die marginale Verteilung dieser beiden zufälligen Teilstichproben zu untersuchen. In einigen Fällen f2f2_3:f1f1_2liegt sie beispielsweise deutlich unter während das geschätzte Modell Werte nahe vorschlägt . Ist die Randverteilung ähnlich? Gibt es einen Fall von unzureichender Überlappung? Vielleicht ist "einfacher" Bootstrap unangemessen und wir müssen die vorliegende Stichprobe in Bezug auf einige der Faktoren schichten.12.4

usεr11852
quelle
Vielen Dank für Ihre Eingabe, die Daten waren verfügbar und konnten unter den angegebenen Links geladen werden. Der Code und die Daten sollten weiterhin reproduzierbar sein.
Valentin