Calcolo del valore p sconosciuto


9

Recentemente stavo eseguendo il debug di uno script R e ho trovato qualcosa di molto strano, l'autore ha definito la propria funzione p-value

pval <- function(x, y){
    if (x+y<20) { # x + y is small, requires R.basic
        p1<- nChooseK(x+y,x) * 2^-(x+y+1);
        p2<- nChooseK(x+y,y) * 2^-(x+y+1);
        pvalue = max(p1, p2)
    }
    else { # if x+y is large, use approximation
        log_p1 <- (x+y)*log(x+y) - x*log(x) - y*log(y) - (x+y+1)*log(2);
        pvalue<-exp(log_p1);
    }
    return(pvalue)
}

Dove X e Y sono valori valori positivi maggiori di 0. Il caso <20 sembra essere un calcolo per un qualche tipo di distribuzione ipergeometrica (qualcosa di simile al test di Fisher?) E qualcuno sa qual è l'altro calcolo? Come sidenote, sto cercando di ottimizzare questo codice, quindi cerco di capire la funzione R corretta da chiamare e sostituirla con.

Modifica: la formula dettagliata dei dettagli cartacei per il calcolo del valore p è disponibile qui (è necessario fare clic su pdf per visualizzare le formule) I metodi iniziano a pagina 8 del pdf e la formula in questione è disponibile a pagina 9 in (1). La distribuzione che assumono è un Poisson.

Risposte:


15

La seconda cosa sembra essere un'approssimazione del calcolo utilizzato per il x+y < 20caso, ma basato sull'approssimazione Stirling .

Normalmente quando viene utilizzato per questo tipo di approssimazione, le persone usano almeno il termine aggiuntivo successivo (il fattore in approssimazione pern! ), che migliorerebbe sostanzialmente l'approssimazione relativa per i piccolin.2πnn!n

Ad esempio, se ed y sono entrambi 10, il primo calcolo dà circa 0,088 mentre l'approssimazione quando il fattore di Xy è incluso in tutti i termini è circa 0,089, abbastanza vicino per la maggior parte degli scopi ... ma omettendo quel termine nell'approssimazione si ottiene 0,5 - che in realtà non è abbastanza vicino! L'autore di quella funzione chiaramente non si è preoccupato di verificare l'accuratezza della sua approssimazione nel caso limite.2πn

A tal fine, l'autore avrebbe probabilmente dovuto semplicemente chiamare la lgammafunzione integrata, in particolare, usando questo invece di quello che ha per log_p1:

log_p1 <- lgamma(x+y+1)-lgamma(x+1)-lgamma(y+1)-(x+y+1)*log(2)

che risulta nella risposta che sta cercando di approssimare (poiché in lgamma(x+1)realtà restituisce il log(X!) , la stessa cosa che sta cercando di approssimare - scarsamente - tramite l'approssimazione Stirling).

Allo stesso modo, non sono sicuro del motivo per cui l'autore non utilizza la choosefunzione incorporata nella prima parte, una funzione che rientra nella distribuzione standard di R. In ogni caso, anche la relativa funzione di distribuzione è probabilmente incorporata.

lgammachoosechoose(1000,500)lgammaXy

Con ulteriori informazioni, dovrebbe essere possibile identificare l'origine del test. Suppongo che lo scrittore l'abbia preso da qualche parte, quindi dovrebbe essere possibile rintracciarlo. Hai qualche contesto per questo?

Quando dici "ottimizza" intendi renderlo più veloce, più breve, più gestibile o qualcos'altro?


Modifica dopo aver letto rapidamente sul foglio:

Gli autori sembrano sbagliati su diversi punti. L'esatto test di Fisher non presuppone che i margini siano fissi, ma semplicemente li condiziona , il che non è affatto la stessa cosa, come discusso, ad esempio, qui , con riferimenti. In effetti, sembrano praticamente del tutto ignari del dibattito sul condizionamento ai margini e sul perché venga fatto. Vale la pena leggere i collegamenti.

[Passano dal "test di Fisher è sempre più conservativo del nostro" all'affermazione che il test di Fisher è troppo conservativo ... il che non segue necessariamente a meno che non sia sbagliato condizionarlo . Dovrebbero affermarlo, ma dato che è qualcosa su cui gli statistici discutono da circa 80 anni, e questi autori sembrano inconsapevoli del perché il condizionamento è fatto, non penso che questi ragazzi siano arrivati ​​al fondo di quel problema .]

Gli autori dell'articolo sembrano almeno capire che le probabilità che danno devono essere cumulate per fornire valori p; per esempio vicino al centro della prima colonna di pagina 5 (enfasi sulla mia):

La significatività statistica secondo l'esatto test di Fisher per tale risultato è del 4,6% (valore P a due code, cioè la probabilità che si verifichi una tabella di questo tipo nell'ipotesi che le frequenze EST dell'actina siano indipendenti dalle librerie di cDNA). In confronto, il valore P calcolato dalla forma cumulativa (Equazione 9, vedi Metodi) dell'equazione 2 (ovvero, affinché la frequenza relativa degli EST attinici sia la stessa in entrambe le librerie, dato che almeno 11 EST cognati sono osservati in la biblioteca del fegato dopo che due sono state osservate nella biblioteca del cervello) è dell'1,6%.

(anche se non sono sicuro di essere d'accordo con il loro calcolo del valore lì; dovrei controllare attentamente per vedere cosa stanno effettivamente facendo con l'altra coda.)

Non penso che il programma lo faccia.

XX+y

Non sono nemmeno convinto che la somma delle loro probabilità sia 1 a questo punto.

C'è molto altro da dire qui, ma la domanda non riguarda il documento, si tratta dell'implementazione nel programma.

-

Comunque, il risultato è che almeno il documento identifica correttamente che i valori p sono costituiti da una somma di probabilità come quelle dell'equazione 2, ma il programma no . (Vedi eqn 9a e 9b nella sezione Metodi del documento.)

Il codice è semplicemente sbagliato su questo.

[Potresti usare pbinom, come implicherebbe il commento di @ whuber, per calcolare le probabilità individuali (ma non la coda, dal momento che non è un test binomiale mentre lo strutturano) ma poi c'è un fattore aggiuntivo di 1/2 nella loro equazione 2 quindi se si desidera replicare i risultati nel documento, è necessario modificarli.]

Puoi ottenerlo, con un po 'di armeggiamento, da pnbinom-

KthKth

(K+r-1K)(1-p)rpK,

p=N1/(N1+N2)K=Xr=y+1

y

Sarebbe male.


1
+1 Bella spiegazione. Ci sono alcuni problemi aggiuntivi con questo codice. Non è necessario calcolare p2affatto; il più piccolo di p1e p2corrisponde al più piccolo di xe y, rispettivamente - questa è un'inefficienza. Un possibile bug è che il secondo ramo del condizionale non riesce p2affatto a calcolare e usa solo p1. Ho anche il sospetto che il codice potrebbe essere del tutto errato, perché non sembra calcolare un valore p: è solo metà della probabilità binomiale e forse dovrebbe essere una probabilità di coda . Perché non usare pbinom/ dbinome finirlo?
whuber

Grazie per l'ottima risposta, sono stato in grado di rintracciare l'origine della formula: genome.cshlp.org/content/7/10/986.short Volevo cambiarlo per essere più veloce e più facile da mantenere / leggere.
yingw,

Grazie per il documento; è stato utile per capire cosa stava succedendo nel codice. Che shemozzle.
Glen_b

1
+1. Questo è un post che non dovrebbe essere wiki della community! Penso che sia dovuto ai 14 giri, ma in questo caso sono tutti da te. La tua diligenza è stata punita!
Darren Cook,

Grazie per il voto di fiducia. Sì, ho continuato a tornare e apportare miglioramenti mentre leggevo il documento, ma immagino che sia colpa mia in parte per non aver raggiunto il risultato finale in modo più efficiente.
Glen_b
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.