¿Cómo obtener valores p agrupados en las pruebas realizadas en múltiples conjuntos de datos imputados?

11

Usando Amelia en R, obtuve múltiples conjuntos de datos imputados. Después de eso, realicé una prueba de medidas repetidas en SPSS. Ahora, quiero agrupar los resultados de las pruebas. Sé que puedo usar las reglas de Rubin (implementadas a través de cualquier paquete de imputación múltiple en R) para agrupar los medios y los errores estándar, pero ¿cómo puedo agrupar los valores p? ¿Es posible? ¿Hay una función en R para hacerlo? Gracias por adelantado.

wisc88
fuente
Es posible que desee consultar información sobre el metanálisis del valor p. Un buen punto de partida: en.wikipedia.org/wiki/Fisher%27s_method
user29889

Respuestas:

13

, es posible y, sí, hay Rfunciones que lo hacen. En lugar de calcular los valores p de los análisis repetidos a mano, puede usar el paquete Zelig, al que también se hace referencia en la viñeta del Ameliapaquete ( para obtener un método más informativo, consulte mi actualización a continuación ). AmeliaUsaré un ejemplo de la viñeta para demostrar esto:

library("Amelia")
data(freetrade)
amelia.out <- amelia(freetrade, m = 15, ts = "year", cs = "country")

library("Zelig")
zelig.fit <- zelig(tariff ~ pop + gdp.pc + year + polity, data = amelia.out$imputations, model = "ls", cite = FALSE)
summary(zelig.fit)

Este es el resultado correspondiente, incluidos los valores :p

  Model: ls
  Number of multiply imputed data sets: 15 

Combined results:

Call:
lm(formula = formula, weights = weights, model = F, data = data)

Coefficients:
                Value Std. Error t-stat  p-value
(Intercept)  3.18e+03   7.22e+02   4.41 6.20e-05
pop          3.13e-08   5.59e-09   5.59 4.21e-08
gdp.pc      -2.11e-03   5.53e-04  -3.81 1.64e-04
year        -1.58e+00   3.63e-01  -4.37 7.11e-05
polity       5.52e-01   3.16e-01   1.75 8.41e-02

For combined results from datasets i to j, use summary(x, subset = i:j).
For separate results, use print(summary(x), subset = i:j).

zeligPuede adaptarse a una gran cantidad de modelos que no sean mínimos cuadrados.

Para obtener intervalos de confianza y grados de libertad para sus estimaciones, puede usar mitools:

library("mitools")
imp.data <- imputationList(amelia.out$imputations)
mitools.fit <- MIcombine(with(imp.data, lm(tariff ~ polity + pop + gdp.pc + year)))
mitools.res <- summary(mitools.fit)
mitools.res <- cbind(mitools.res, df = mitools.fit$df)
mitools.res

Esto le dará intervalos de confianza y una proporción de la varianza total atribuible a los datos faltantes:

              results       se    (lower    upper) missInfo    df
(Intercept)  3.18e+03 7.22e+02  1.73e+03  4.63e+03     57 %  45.9
pop          3.13e-08 5.59e-09  2.03e-08  4.23e-08     19 % 392.1
gdp.pc      -2.11e-03 5.53e-04 -3.20e-03 -1.02e-03     21 % 329.4
year        -1.58e+00 3.63e-01 -2.31e+00 -8.54e-01     57 %  45.9
polity       5.52e-01 3.16e-01 -7.58e-02  1.18e+00     41 %  90.8

Por supuesto, puede combinar los resultados interesantes en un solo objeto:

combined.results <- merge(mitools.res, zelig.res$coefficients[, c("t-stat", "p-value")], by = "row.names", all.x = TRUE)

Actualizar

Después de jugar un poco, he encontrado una forma más flexible de obtener toda la información necesaria usando el micepaquete. Para que esto funcione, deberá modificar la función del paquete as.mids(). Use la versión de Gerko publicada en mi pregunta de seguimiento :

as.mids2 <- function(data2, .imp=1, .id=2){
  ini <- mice(data2[data2[, .imp] == 0, -c(.imp, .id)], m = max(as.numeric(data2[, .imp])), maxit=0)
  names  <- names(ini$imp)
  if (!is.null(.id)){
    rownames(ini$data) <- data2[data2[, .imp] == 0, .id]
  }
  for (i in 1:length(names)){
    for(m in 1:(max(as.numeric(data2[, .imp])))){
      if(!is.null(ini$imp[[i]])){
        indic <- data2[, .imp] == m & is.na(data2[data2[, .imp]==0, names[i]])
        ini$imp[[names[i]]][m] <- data2[indic, names[i]]
      }
    } 
  }
  return(ini)
}

Con esto definido, puede continuar analizando los conjuntos de datos imputados:

library("mice")
imp.data <- do.call("rbind", amelia.out$imputations)
imp.data <- rbind(freetrade, imp.data)
imp.data$.imp <- as.numeric(rep(c(0:15), each = nrow(freetrade)))
mice.data <- as.mids2(imp.data, .imp = ncol(imp.data), .id = NULL)

mice.fit <- with(mice.data, lm(tariff ~ polity + pop + gdp.pc + year))
mice.res <- summary(pool(mice.fit, method = "rubin1987"))

Esto le dará todos los resultados que se obtienen utilizando Zeligy mitoolsmás:

                  est       se     t    df Pr(>|t|)     lo 95     hi 95 nmis   fmi lambda
(Intercept)  3.18e+03 7.22e+02  4.41  45.9 6.20e-05  1.73e+03  4.63e+03   NA 0.571  0.552
pop          3.13e-08 5.59e-09  5.59 392.1 4.21e-08  2.03e-08  4.23e-08    0 0.193  0.189
gdp.pc      -2.11e-03 5.53e-04 -3.81 329.4 1.64e-04 -3.20e-03 -1.02e-03    0 0.211  0.206
year        -1.58e+00 3.63e-01 -4.37  45.9 7.11e-05 -2.31e+00 -8.54e-01    0 0.570  0.552
polity       5.52e-01 3.16e-01  1.75  90.8 8.41e-02 -7.58e-02  1.18e+00    2 0.406  0.393

Tenga en cuenta que con el uso pool()también puede calcular los valores con ajustado para muestras pequeñas omitiendo el parámetro. Lo que es aún mejor, ahora también puede calcular y comparar modelos anidados:d f R 2pdfmethodR2

pool.r.squared(mice.fit)

mice.fit2 <- with(mice.data, lm(tariff ~ polity + pop + gdp.pc))
pool.compare(mice.fit, mice.fit2, method = "Wald")$pvalue
crsh
fuente
1
Gran respuesta, sólo quería señalar un ligero error tipográfico, creo que quería decir: mice.res <- summary(pool(mice.fit, method = "rubin1987")).
FrankD
Buena atrapada. He corregido el error tipográfico.
crsh
8

Normalmente, tomaría el valor p aplicando las reglas de Rubin en parámetros estadísticos convencionales como los pesos de regresión. Por lo tanto, a menudo no es necesario agrupar los valores p directamente. Además, la estadística de razón de probabilidad se puede agrupar para comparar modelos. Los procedimientos de agrupación para otras estadísticas se pueden encontrar en mi libro Imputación flexible de datos faltantes, capítulo 6.

En los casos en que no se conoce una distribución o método, existe un procedimiento no publicado por Licht y Rubin para las pruebas unilaterales. Utilicé este procedimiento para agrupar los valores p del wilcoxon()procedimiento, pero es general y sencillo adaptarse a otros usos.

Use el procedimiento a continuación SOLAMENTE si todo lo demás falla, ya que por ahora, sabemos poco acerca de sus propiedades estadísticas.

lichtrubin <- function(fit){
    ## pools the p-values of a one-sided test according to the Licht-Rubin method
    ## this method pools p-values in the z-score scale, and then transforms back 
    ## the result to the 0-1 scale
    ## Licht C, Rubin DB (2011) unpublished
    if (!is.mira(fit)) stop("Argument 'fit' is not an object of class 'mira'.")
    fitlist <- fit$analyses
        if (!inherits(fitlist[[1]], "htest")) stop("Object fit$analyses[[1]] is not an object of class 'htest'.")
    m <- length(fitlist)
    p <- rep(NA, length = m)
    for (i in 1:m) p[i] <- fitlist[[i]]$p.value
    z <- qnorm(p)  # transform to z-scale
    num <- mean(z)
    den <- sqrt(1 + var(z))
    pnorm( num / den) # average and transform back
}
Stef van Buuren
fuente
@ Stef van Buuren, ¿qué quiere decir con 'tomar el valor p aplicando las reglas de Rubin en parámetros estadísticos convencionales como los pesos de regresión'? ¿Cómo llega la pool() función en su paquete (que es excelente por cierto) al valor p agrupado?
llewmills