Comment obtenir des valeurs de p regroupées sur des tests effectués dans plusieurs jeux de données imputés?

11

En utilisant Amelia dans R, j'ai obtenu plusieurs jeux de données imputés. Après cela, j'ai effectué un test de mesures répétées dans SPSS. Maintenant, je veux regrouper les résultats des tests. Je sais que je peux utiliser les règles de Rubin (implémentées via n'importe quel package d'imputation multiple dans R) pour regrouper les moyennes et les erreurs standard, mais comment regrouper les valeurs p? C'est possible? Y a-t-il une fonction dans R pour le faire? Merci d'avance.

wisc88
la source
Vous voudrez peut-être consulter des informations sur la méta-analyse de la valeur de p. Un bon point de départ: en.wikipedia.org/wiki/Fisher%27s_method
user29889

Réponses:

13

Oui , c'est possible et, oui, il y a des Rfonctions qui le font. Au lieu de calculer manuellement les valeurs de p des analyses répétées, vous pouvez utiliser le package Zelig, qui est également mentionné dans la vignette du Amelia-package ( pour une méthode plus informative, voir ma mise à jour ci-dessous ). Je vais utiliser un exemple de la Amelia-vignette pour le démontrer:

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)

Il s'agit de la sortie correspondante, y compris les valeurs :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).

zeligpeut s'adapter à une multitude de modèles autres que les moindres carrés.

Pour obtenir des intervalles de confiance et des degrés de liberté pour vos estimations, vous pouvez utiliser 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

Cela vous donnera des intervalles de confiance et une proportion de la variance totale attribuable aux données manquantes:

              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

Bien sûr, vous pouvez simplement combiner les résultats intéressants en un seul objet:

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

Mise à jour

Après avoir joué, j'ai trouvé un moyen plus flexible d'obtenir toutes les informations nécessaires en utilisant le micepaquet. Pour que cela fonctionne, vous devrez modifier la fonction du package as.mids(). Utilisez la version de Gerko publiée dans ma question de suivi :

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)
}

Une fois ceci défini, vous pouvez continuer à analyser les ensembles de données imputées:

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"))

Cela vous donnera tous les résultats que vous obtenez en utilisant Zeliget mitoolsen plus:

                  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

Remarque: en utilisant, pool()vous pouvez également calculer les valeurs de avec ajusté pour les petits échantillons en omettant le paramètre-. Ce qui est encore mieux, vous pouvez désormais également calculer et comparer les modèles imbriqués:pFmethodR2

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
la source
1
Grande réponse, je voulais juste faire remarquer une légère faute de frappe, je pense que vous vouliez dire: mice.res <- summary(pool(mice.fit, method = "rubin1987")).
FrankD
Bonne prise. J'ai corrigé la faute de frappe.
crsh
8

Normalement, vous prendriez la valeur de p en appliquant les règles de Rubin sur les paramètres statistiques conventionnels comme les poids de régression. Ainsi, il n'est souvent pas nécessaire de regrouper les valeurs p directement. De plus, la statistique du rapport de vraisemblance peut être regroupée pour comparer les modèles. Les procédures de mise en commun d'autres statistiques se trouvent dans mon livre Flexible Imputation of Missing Data, chapitre 6.

Dans les cas où il n'y a pas de distribution ou de méthode connue, il existe une procédure non publiée par Licht et Rubin pour les tests unilatéraux. J'ai utilisé cette procédure pour regrouper les valeurs p de la wilcoxon()procédure, mais il est général et simple de s'adapter à d'autres utilisations.

Utilisez la procédure ci-dessous UNIQUEMENT si tout le reste échoue, car pour l'instant, nous savons peu de choses sur ses propriétés statistiques.

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
la source
@ Stef van Buuren que voulez-vous dire par «prendre la valeur de p en appliquant les règles de Rubin sur des paramètres statistiques conventionnels comme les poids de régression»? Comment la pool() fonction de votre package (qui est excellente d'ailleurs) arrive-t-elle à la valeur p groupée?
llewmills