Test de randomisation / permutation pour les vecteurs appariés dans R

9

Je ne suis pas un expert, alors pardonnez-moi si une partie de la terminologie est un peu maladroite. Heureux de fournir plus d'informations si nécessaire.

J'ai deux vecteurs de 50 valeurs numériques appariées dans R. Je veux effectuer un test de randomisation ou de permutation bilatéral pour déterminer si leurs différences sont dues au hasard ou non.

Un test de permutation (également appelé test de randomisation, test de re-randomisation ou test exact) est un type de test de signification statistique dans lequel la distribution de la statistique de test sous l'hypothèse nulle est obtenue en calculant toutes les valeurs possibles de la statistique de test sous réarrangements des étiquettes sur les points de données observés.

Je veux faire ce type de test car je pense que les distributions des valeurs dans les vecteurs violent les hypothèses d'autres tests tels que le test t (par exemple, la plupart des valeurs numériques dans le vecteur sont 0).

La permtestfonction de la bibliothèque BHH2 fait presque ce que je veux, mais elle fonctionne sur toutes les permutations, ce qui prendra trop de temps. Au lieu de cela, je veux estimer la valeur de p, en échantillonnant un grand nombre des permutations possibles. J'ai jeté un coup d'œil dans le paquet de pièces , mais rien ne semble faire de test de permutation avec un échantillonnage à partir de vecteurs numériques appariés.250

Certains googleurs m'ont conduit à cet e-mail , ce qui suggère que la raison pour laquelle je ne trouve pas de package pour le faire est que c'est un one-liner en R. Malheureusement, je n'ai pas assez d'expérience avec R pour pouvoir produire celui-là -doublure.

Existe-t-il un package ou une méthode qui effectuera un test de permutation apparié bilatéral en utilisant uniquement un échantillon de l'espace de permutation?

Sinon, quelqu'un pourrait-il partager un petit bout de code R pour le faire?

Timothy Jones
la source
3
Il me semble que le package coin(parmi plusieurs autres) fait des tests de randomisation. par exemple voir la réponse à cette question (lire le tout) . Si je comprends bien, les exemples couvrent des cas approximatifs et exacts et couvrent des échantillons indépendants et dépendants.
Glen_b -Reinstate Monica
1
Désolé, pour être clair - par «lire le tout», je veux dire «lire la réponse du haut tout au long» - bien que vous souhaitiez également regarder la réponse du bas.
Glen_b -Reinstate Monica
À peu près le seul morceau intéressant de cette réponse pour les permutations appariées est oneway_test(y ~ x | pairs, distribution=approximate(B=9999))avec library(coin).
Nakx

Réponses:

12

Bien que j'aie souligné dans les commentaires l'utilisation du coinpackage, je pense qu'il vaut la peine d'illustrer qu'un test de permutation / randomisation est vraiment assez simple, donc je l'ai fait.

Ici, j'écris du code R pour faire un test de randomisation pour un test de localisation d'un échantillon. Le test retourne au hasard les signes sur les différences et calcule la moyenne; cela revient à attribuer aléatoirement chaque paire de valeurs aux groupes x et y. Le code ci-dessous pourrait être considérablement raccourci (je pourrais le faire en deux lignes assez facilement, ou même une si cela ne vous dérangeait pas).

Ce code prend quelques secondes sur ma machine:

# assumes the two samples are in 'x' and 'y' and x[i] and y[i] are paired
# set up:
B <- 99999
d <- x-y
m0 <- mean(d)

# perform a one-sample randomization test on d
# for the null hypothesis H0: mu_d = 0   vs H1 mu_d != 0  (i.e. two tailed)
# here the test statistic is the mean
rndmdist <- replicate(B,mean((rbinom(length(d),1,.5)*2-1)*d))

# two tailed p-value:
sum( abs(rndmdist) >= abs(m0))/length(rndmdist)

Voilà tout.

Notez que cela rbinom(length(d),1,.5)*2-1)donne un signe aléatoire -1ou 1... c'est-à-dire un signe aléatoire, donc quand nous multiplions par n'importe quel ensemble de signé d, cela équivaut à assigner au hasard +ou des -signes aux différences absolues. [Peu importe la distribution des signes sur laquelle dvous commencez, maintenant dils auront des signes aléatoires.]

Ici, je le compare avec un test t sur certaines données composées:

 set.seed(seed=438978)
 z=rnorm(50,10,2)
 x=z-rnorm(50,0,.5)
 y=z+.4+rnorm(50,0,.5)
 t.test(y-x) # gives p = 0.003156

 B <- 99999
 d <- x-y
 m0 <- mean(d)
 rndmdist <- replicate(B,mean((rbinom(length(d),1,.5)*2-1)*d))
 sum( abs(rndmdist) >= abs(m0))/length(rndmdist) 

Lorsque le test t est valide, il donne généralement une valeur p très similaire au test de permutation complètement énuméré, et une valeur p simulée comme ci-dessus (lorsque le nombre de simulations est suffisamment grand) convergera vers cette deuxième valeur p.

Au nombre de réplications utilisé ci-dessus, une vraie valeur p de permutation (c.-à-d. À partir d'un dénombrement complet) de 0,05 sera estimée à moins de 0,001 (c'est-à-dire, donnera une valeur p de randomisation entre 0,049 et 0,051) dans environ 85% des cas. et à 0,002% près de 99,5% du temps.

Glen_b -Reinstate Monica
la source
Très apprécié, merci. Comment avez-vous calculé la précision de la valeur de p?
Timothy Jones
1
C'est juste l' approximation normale d'une proportion binomiale , en utilisant l' erreur standard d'une proportion ; . s.e.(p^)=p(1p)/n
Glen_b -Reinstate Monica
Pourquoi multipliez-vous la fonction rbinom par 2-1? Et puis d?
Pour obtenir des signes aléatoires d, car c'est ainsi que fonctionne un test de permutation de la différence moyenne pour les données appariées. Voir de nouveaux commentaires supplémentaires après ce morceau de code.
Glen_b -Reinstate Monica
1
@Joe lorsque nous ajoutons l'échantillon observé, il fera un nombre rond
Glen_b -Reinstate Monica
0

Voici le code pour effectuer un test de permutation. J'ai des données par exemple. x est la différence entre les deux vecteurs.

x <- c(5.1, 9.4, 7.2, 8.1, 8.8, 2.5, 4.2, 6.9, 5.5, 5.3)
m = 5
n = 5
xsum = sum(x)
asum = sum(x[1:m])
bsum = xsum - asum
truediff = asum/m - bsum/n
truediff
abstruediff = abs(truediff)
iter = 100000
difflist <- 1:iter
for(i in 1:iter) {
  s <- sample(x,m) # select a sample of size m
  pasum = sum(s)
  pbsum = sum(x) - sum(s)
  diff  = pasum/m - pbsum/n
  difflist[i] <- diff # add permutation difference to list
}
difflist  <- sort(difflist)
xquantile <- quantile(difflist,probs=c(.005, .01, .025, .05, .95, .975, .99, .995))
xquantile
pdist  <- quantile(difflist, probs=seq(0,1,1/iter))
ntail1 <- length(pdist[difflist <= -abstruediff])
tail1  <- ntail1/iter
tail1  # left-tail probability
ntail2 <- length(pdist[difflist >= abstruediff])
tail2  <- ntail2/iter
tail2  # right-tail probability
twotail = tail1 + tail2
twotail 
Lauren Goodwin
la source