Quale implementazione del test di permutazione in R usare al posto dei test t (accoppiati e non accoppiati)?


56

Ho i dati di un esperimento che ho analizzato usando i test t. La variabile dipendente viene ridimensionata in base all'intervallo e i dati sono non accoppiati (ovvero, 2 gruppi) o accoppiati (ovvero, all'interno dei soggetti). Ad esempio (all'interno dei soggetti):

x1 <- c(99, 99.5, 65, 100, 99, 99.5, 99, 99.5, 99.5, 57, 100, 99.5, 
        99.5, 99, 99, 99.5, 89.5, 99.5, 100, 99.5)
y1 <- c(99, 99.5, 99.5, 0, 50, 100, 99.5, 99.5, 0, 99.5, 99.5, 90, 
        80, 0, 99, 0, 74.5, 0, 100, 49.5)

Tuttavia, i dati non sono normali, quindi un revisore ci ha chiesto di utilizzare qualcosa di diverso dal test t. Tuttavia, come si può facilmente vedere, i dati non solo non sono normalmente distribuiti, ma le distribuzioni non sono uguali tra le condizioni: testo alternativo

Pertanto, i soliti test non parametrici, il test Mann-Whitney-U (non accoppiato) e il test Wilcoxon (accoppiato), non possono essere utilizzati in quanto richiedono pari distribuzioni tra le condizioni. Quindi, ho deciso che alcuni test di ricampionamento o di permutazione sarebbero stati i migliori.

Ora sto cercando un'implementazione R di un equivalente basato su permutazione del test t, o qualsiasi altro consiglio su cosa fare con i dati.

So che ci sono alcuni pacchetti R che possono farlo per me (ad esempio, coin, perm, esattaRankTest, ecc.), Ma non so quale scegliere. Quindi, se qualcuno con una certa esperienza nell'uso di questi test potesse darmi un calcio d'inizio, sarebbe superfluo.

AGGIORNAMENTO: Sarebbe l'ideale se potessi fornire un esempio di come riportare i risultati di questo test.

Risposte:


43

Non dovrebbe importare molto poiché la statistica del test sarà sempre la differenza nei mezzi (o qualcosa di equivalente). Piccole differenze possono venire dall'implementazione dei metodi Monte-Carlo. Prova i tre pacchetti con i tuoi dati con un test unilaterale per due variabili indipendenti:

DV <- c(x1, y1)
IV <- factor(rep(c("A", "B"), c(length(x1), length(y1))))
library(coin)                    # for oneway_test(), pvalue()
pvalue(oneway_test(DV ~ IV, alternative="greater", 
                   distribution=approximate(B=9999)))
[1] 0.00330033

library(perm)                    # for permTS()
permTS(DV ~ IV, alternative="greater", method="exact.mc", 
       control=permControl(nmc=10^4-1))$p.value
[1] 0.003

library(exactRankTests)          # for perm.test()
perm.test(DV ~ IV, paired=FALSE, alternative="greater", exact=TRUE)$p.value
[1] 0.003171822

Per verificare il valore p esatto con un calcolo manuale di tutte le permutazioni, limiterò i dati ai primi 9 valori.

x1 <- x1[1:9]
y1 <- y1[1:9]
DV <- c(x1, y1)
IV <- factor(rep(c("A", "B"), c(length(x1), length(y1))))
pvalue(oneway_test(DV ~ IV, alternative="greater", distribution="exact"))
[1] 0.0945907

permTS(DV ~ IV, alternative="greater", exact=TRUE)$p.value
[1] 0.0945907

# perm.test() gives different result due to rounding of input values
perm.test(DV ~ IV, paired=FALSE, alternative="greater", exact=TRUE)$p.value
[1] 0.1029412

# manual exact permutation test
idx  <- seq(along=DV)                 # indices to permute
idxA <- combn(idx, length(x1))        # all possibilities for different groups

# function to calculate difference in group means given index vector for group A
getDiffM <- function(x) { mean(DV[x]) - mean(DV[!(idx %in% x)]) }
resDM    <- apply(idxA, 2, getDiffM)  # difference in means for all permutations
diffM    <- mean(x1) - mean(y1)       # empirical differencen in group means

# p-value: proportion of group means at least as extreme as observed one
(pVal <- sum(resDM >= diffM) / length(resDM))
[1] 0.0945907

coine exactRankTestssono entrambi dello stesso autore, ma coinsembra essere più generale ed esteso, anche in termini di documentazione. exactRankTestsnon è più sviluppato attivamente. Quindi sceglierei coin(anche a causa di funzioni informative come support()), a meno che non ti piaccia occuparsi degli oggetti S4.

EDIT: per due variabili dipendenti, la sintassi è

id <- factor(rep(1:length(x1), 2))    # factor for participant
pvalue(oneway_test(DV ~ IV | id, alternative="greater",
                   distribution=approximate(B=9999)))
[1] 0.00810081

Grazie per l'ottima risposta! Altre 2 domande: Il tuo secondo esempio significa che quella moneta in realtà fornisce tutte le possibili permutazioni ed è un test esatto? C'è qualche vantaggio nel non fornire un test esatto nel mio caso?
Henrik

10
(+1) Non sorprende che il test t (non abbinato) fornisca essenzialmente lo stesso valore p, 0.000349. Nonostante quanto affermato dal revisore, il test t è applicabile a questi dati. Il motivo è che le distribuzioni campionarie dei mezzi sono approssimativamente normali, anche se le distribuzioni dei dati non lo sono. Inoltre, come puoi vedere dai risultati, il test t è in realtà più conservativo rispetto al test di permutazione. (Ciò significa che un risultato significativo con il test t indica che anche il test di permutazione sarà probabilmente significativo.)
whuber

2
@Henrik Per determinate situazioni (test scelto e complessità numerica), coinpuò effettivamente calcolare l'esatta distribuzione delle permutazioni (senza effettivamente passare attraverso tutte le permutazioni, ci sono algoritmi più eleganti di quello). Data la scelta, la distribuzione esatta sembra preferibile, ma la differenza con un'approssimazione di Monte-Carlo con un alto numero di repliche dovrebbe essere piccola.
Caracal,

1
@Caracal Grazie per il chiarimento. Rimane una domanda: i dati che ho presentato sono accoppiati. Quindi, ho bisogno dell'equivalente del t-test associato. La oneway_testfunzione è accurata? E in caso affermativo, qual è il corretto per i dati non associati?
Henrik

2
@Henrik L' coinautore mi ha scritto che oneway_test()non è possibile calcolare l'esatta distribuzione per il caso dipendente, devi andare con l'approssimazione MC ( wilcoxsign_test()è adatto solo per il test esatto). Non lo sapevo e avrei preferito un errore in quel caso, ma MC dovrebbe essere abbastanza preciso con un alto numero di repliche.
Caracal,

29

Alcuni commenti sono, credo, in ordine.

1) Ti incoraggio a provare più visualizzazioni visive dei tuoi dati, perché possono catturare cose che sono perse da (istogrammi come) istogrammi e ti consiglio vivamente di tracciare gli assi affiancati. In questo caso, non credo che gli istogrammi facciano un ottimo lavoro nel comunicare le caratteristiche salienti dei tuoi dati. Ad esempio, dai un'occhiata ai grafici a scatole affiancate:

boxplot(x1, y1, names = c("x1", "y1"))

testo alternativo

O anche i diagrammi a strisce affiancati:

stripchart(c(x1,y1) ~ rep(1:2, each = 20), method = "jitter", group.names = c("x1","y1"), xlab = "")

testo alternativo

x1y1x1y1x1y1y1

2) Non hai spiegato in dettaglio da dove provengono i tuoi dati, né come sono stati misurati, ma queste informazioni sono molto importanti quando arriva il momento di selezionare una procedura statistica. I tuoi due campioni sopra sono indipendenti? Vi sono ragioni per ritenere che le distribuzioni marginali dei due campioni debbano essere le stesse (tranne che per una differenza di posizione, ad esempio)? Quali erano le considerazioni precedenti allo studio che ti hanno portato a cercare prove di una differenza tra i due gruppi?

zpp

p

5) Secondo me, questi dati sono un perfetto (?) Esempio che un'immagine ben scelta vale 1000 test di ipotesi. Non abbiamo bisogno di statistiche per dire la differenza tra una matita e un fienile. La dichiarazione appropriata a mio avviso per questi dati sarebbe "Questi dati mostrano marcate differenze rispetto a posizione, scala e forma". Puoi dare seguito a statistiche descrittive (solide) per ognuna di esse per quantificare le differenze e spiegare cosa significano le differenze nel contesto del tuo studio originale.

pp

Questa risposta è molto più lunga di quanto pensassi inizialmente. Mi dispiace per quello.


Sono curioso di prendere in considerazione il seguente approccio quasi visualizzato: stime bootstrap per i momenti dei due gruppi (media, varianze e momenti più alti se lo desideri) quindi tracciare queste stime e i loro intervalli di confidenza, cercando per il grado di sovrapposizione tra i gruppi in ogni momento. Ciò consente di parlare delle potenziali differenze tra le varie caratteristiche di distribuzione. Se i dati sono accoppiati, calcola i punteggi delle differenze e avvia i momenti di questa singola distribuzione. Pensieri?
Mike Lawrence,

2
(+1) Buona analisi. Hai perfettamente ragione sul fatto che i risultati sono ovvi e non è necessario premere il punto con un valore p. Potresti essere un po 'estremo nella tua dichiarazione di (3), perché il test t non richiede dati normalmente distribuiti. Se sei preoccupato, esistono degli aggiustamenti per l'asimmetria (ad esempio, la variante di Chen): potresti vedere se il valore p per il test modificato cambia la risposta. In caso contrario, probabilmente stai bene. In questa particolare situazione, con questi dati (molto distorti), il test t funziona bene.
whuber

(+1) Bella cattura! E ottimi commenti.
chl

Sembra che accettiamo l'idea che la distribuzione sottostante sia "simile" all'istanza casuale. Quindi non si potrebbe porre la domanda: sono entrambi entrambi da beta (0,25, 0,25) e quindi il test sarebbe se hanno lo stesso parametro (non) di centralità. E ciò non giustificherebbe l'uso di un test di permutazione o di Wilcoxon?
DWin

4

5

I miei commenti non riguardano l'implementazione del test di permutazione, ma le questioni più generali sollevate da questi dati e la loro discussione, in particolare il post di G. Jay Kerns.

Le due distribuzioni in realtà sembrano abbastanza simili a me TRANNE il gruppo di 0 in Y1, che sono molto diverse dalle altre osservazioni in quel campione (il più piccolo successivo è di circa 50 sulla scala 0-100) così come tutti quelli in X1. In primo luogo vorrei indagare se ci fosse qualcosa di diverso in quelle osservazioni.

In secondo luogo, supponendo che quegli 0 appartengano all'analisi, dicendo che il test di permutazione non è valido perché le distribuzioni sembrano differire pone la domanda. Se il valore nullo fosse vero (le distribuzioni sono identiche), potresti (con ragionevole probabilità) che le distribuzioni sembrino diverse da queste due? Rispondere è questo il punto del test, no? Forse in questo caso alcuni considereranno la risposta ovvia senza eseguire il test, ma con queste piccole e peculiari distribuzioni, non credo che lo farei.


Sembra che questo dovrebbe essere uno o più commenti, non una risposta. Se fai clic sul piccolo "aggiungi commento" grigio, puoi inserire i tuoi pensieri nella conversazione sotto la domanda o una risposta particolare, a cui appartengono. Fai qui dei punti sostanziali, ma non è chiaro che questo non è il posto adatto per loro.
gung - Ripristina Monica

1
@gung Ci vuole un po 'di reputazione per poter pubblicare un commento ;-).
whuber

4
2(1/2)7.01

4

Man mano che questa domanda si ripresenta, posso aggiungere un'altra risposta ispirata a un recente post sul blog tramite R-Blogger di Robert Kabacoff, l'autore di Quick-R e R in azione usando il lmPermpacchetto.

Tuttavia, questo metodo produce risultati nettamente contrastanti (e molto instabili) rispetto a quello prodotto dal coinpacchetto nella risposta di @caracakl (il valore p dell'analisi all'interno dei soggetti è 0.008). L'analisi prende anche la preparazione dei dati dalla risposta di @ caracal:

x1 <- c(99, 99.5, 65, 100, 99, 99.5, 99, 99.5, 99.5, 57, 100, 99.5, 
        99.5, 99, 99, 99.5, 89.5, 99.5, 100, 99.5)
y1 <- c(99, 99.5, 99.5, 0, 50, 100, 99.5, 99.5, 0, 99.5, 99.5, 90, 
        80, 0, 99, 0, 74.5, 0, 100, 49.5)

DV <- c(x1, y1)
IV <- factor(rep(c("A", "B"), c(length(x1), length(y1))))
id <- factor(rep(1:length(x1), 2)) 

library(lmPerm)

summary(aovp( DV ~ IV + Error(id)))

produce:

> summary(aovp( DV ~ IV + Error(id)))
[1] "Settings:  unique SS "

Error: id
Component 1 :
          Df R Sum Sq R Mean Sq
Residuals 19    15946       839


Error: Within
Component 1 :
          Df R Sum Sq R Mean Sq Iter Pr(Prob)  
IV         1     7924      7924 1004    0.091 .
Residuals 19    21124      1112                
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Se lo esegui più volte, i valori p saltano tra ~ .05 e ~ .1.

Sebbene sia una risposta alla domanda, mi permetta di porre una domanda alla fine (posso spostarla su una nuova domanda, se lo si desidera):
qualsiasi idea del perché questa analisi sia così instabile e produca valori p così divergenti per l'analisi della moneta? Ho fatto qualcosa di male?


2
Potrebbe essere meglio porlo come una domanda separata, se è davvero una domanda a cui vuoi rispondere, piuttosto che un'altra possibile soluzione che desideri elencare con il resto. Ho notato che si specifica uno strato di errore, ma @caracal no; sarebbe la mia prima ipotesi sulla differenza tra questa uscita e la sua. Inoltre, durante la simulazione, i valori in genere saltano intorno; per la riproducibilità, si specifica il seme, ad esempio set.seed(1); per una maggiore precisione nella stima MC, si aumenta il numero di iterazioni; Non sono sicuro che una di queste sia la risposta "giusta" alla tua domanda, ma probabilmente sono pertinenti.
gung - Ripristina Monica

2
Ancora una volta, suggerisco di confrontare i risultati MC con i calcoli manuali usando il test di permutazione completa (ri-randomizzazione). Vedi il codice del tuo esempio per un confronto tra oneway_anova()(sempre vicino al risultato corretto) e aovp()(in genere lontano dal risultato corretto). Non so perché aovp()dia risultati selvaggiamente variabili, ma almeno per questo caso qui non sono plausibili. @gung l'ultima chiamata a oneway_test(DV ~ IV | id, ...)nella mia risposta originale ha specificato gli strati di errore per il caso dipendente (sintassi diversa da quella utilizzata da aov()).
Caracal,

@caracal, hai ragione. Non ho guardato l'ultimo blocco di codice dopo la modifica. Stavo guardando il blocco di codice in alto - sciatto da parte mia.
gung - Ripristina Monica

Non ho davvero bisogno della risposta. È solo un'altra possibilità che vale la pena menzionare qui. Sfortunatamente è lontano dagli altri risultati che valgo anche la pena notare.
Henrik,

1
@Henrik run aovp con maxExact = 1000. Se impiega troppo tempo, impostare iter = 1000000 e Ca = 0,001. Il calcolo termina quando l'errore standard stimato di p è inferiore a Ca * p. (Valori più bassi danno risultati più stabili.)
xmjx

1

Questi punteggi sono proporzioni? In tal caso, non dovresti certamente usare un test parametrico gaussiano e mentre potresti procedere con un approccio non parametrico come un test di permutazione o un bootstrap dei mezzi, suggerirei che otterrai più potere statistico da impiegando un approccio parametrico non gaussiano adatto. In particolare, ogni volta che è possibile calcolare una misura proporzionale all'interno di un'unità di interesse (es. Partecipante a un esperimento), è possibile e probabilmente utilizzare un modello di effetti misti che specifica osservazioni con errore binomialmente distribuito. Vedi Dixon 2004 .


I punteggi non sono proporzioni ma stime dei partecipanti su una scala da 0 a 100 (i dati presentati sono mezzi di stima su diversi articoli con quella scala).
Henrik

Quindi i non parametrici sembrerebbero il modo tradizionale di procedere. Detto questo, mi chiedevo se tali dati di scala potessero essere utilmente dedotti a derivare da un processo binomiale e quindi analizzati come tali. Cioè, dici che ogni punteggio è la media di diversi articoli, e diciamo che ogni articolo ha una scala di 10 punti, nel qual caso rappresenterei una risposta, diciamo, "8" come una serie di prove, 8 di che hanno il valore 1 e due dei quali hanno il valore 0, tutti etichettati con la stessa etichetta in una variabile "item". Con questi dati espansi / binomiali, è quindi possibile calcolare il modello binomiale di effetti misti.
Mike Lawrence,

A seguito del mio commento precedente, dovrei notare che nei dati espansi / binomiali, è possibile modellare la variabile "item" come effetto fisso o casuale. Penso che mi spingerei a modellarlo come un effetto fisso perché presumibilmente potresti essere interessato non solo alla contabilizzazione, ma anche alla valutazione delle differenze dell'articolo e di ogni possibile interazione tra l'articolo e altre variabili predittive.
Mike Lawrence,

0

Basta aggiungere un altro approccio, ezPermdel ezpacchetto:

> # preparing the data
> DV <- c(x1, y1)
> IV <- factor(rep(c("A", "B"), c(length(x1), length(y1))))
> id <- factor(rep(1:length(x1), 2))
> df <- data.frame(id=id,DV=DV,IV=IV)
>
> library(ez)
> ezPerm( data = df, dv = DV, wid = id, within = IV, perms = 1000)
|=========================|100%              Completed after 17 s 
  Effect     p p<.05
1     IV 0.016     *

Questo sembra essere coerente con oneway_testil coinpacchetto:

> library(coin)
> pvalue(oneway_test(DV ~ IV | id,  distribution=approximate(B=999999)))
[1] 0.01608002
99 percent confidence interval:
 0.01575782 0.01640682

Tuttavia, si noti che questo non è lo stesso esempio fornito da @caracal . Nel suo esempio, include alternative="greater", quindi, la differenza tra i valori di p ~0.008e ~0.016.

Il aovppacchetto ha suggerito in una delle risposte produrre sospetto abbassare valori di p, e corre con sospetto veloce anche quando provo valori elevati per il Iter, Cae maxItergli argomenti:

library(lmPerm)
summary(aovp(DV ~ IV + Error(id/IV), data=df,  maxIter = 1000000000))
summary(aovp(DV ~ IV + Error(id/IV), data=df,  Iter = 1000000000))
summary(aovp(DV ~ IV + Error(id/IV), data=df,  Ca = 0.00000000001))

Detto questo, gli argomenti sembrano ridurre leggermente le variazioni dei valori p da ~.03e ~.1(ho ottenuto un intervallo più ampio rispetto a quello riportato da @Henrik), a 0.03e 0.07.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.