Cálculo de valor p desconhecido

9

Eu estava depurando recentemente um script R e achei algo muito estranho, o autor definiu sua própria função de valor p

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

Onde X e Y são valores valores positivos maiores que 0. O caso <20 parece ser um cálculo para algum tipo de distribuição hipergeométrica (algo semelhante ao teste de Fisher?) E alguém sabe qual é o outro cálculo? Como nota de rodapé, estou tentando otimizar esse código, tentando descobrir a função R adequada para chamar e substituir isso.

Edit: A fórmula de detalhamento do papel para o cálculo do valor-p pode ser encontrada aqui (é necessário clicar em pdf para ver as fórmulas) Os métodos começam na página 8 do pdf e a fórmula em questão pode ser encontrada na página 9 em (1). A distribuição que eles assumem é um Poisson.

yingw
fonte

Respostas:

15

A segunda coisa parece ser uma aproximação ao cálculo que está sendo usado para o x+y < 20caso, mas com base na aproximação de Stirling .

Normalmente, quando está sendo usado para esse tipo de aproximação, as pessoas usariam pelo menos o próximo termo adicional (o fator na aproximação para ), O que melhoraria substancialmente a aproximação relativa para pequeno .2πnn!n

Por exemplo, se e são 10, o primeiro cálculo fornece cerca de 0,088 enquanto a aproximação quando o fator está incluído em todos os termos é de cerca de 0,089, perto o suficiente para a maioria dos propósitos ... mas omitir esse termo na aproximação resulta em 0,5 - o que realmente não é suficientemente próximo! O autor dessa função claramente não se preocupou em verificar a precisão de sua aproximação no caso limite.xy2πn

Para esse propósito, o autor provavelmente deveria simplesmente ter chamado a lgammafunção interna - especificamente, usando isso em vez do que ele tem para log_p1:

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

o que resulta na resposta que ele está tentando aproximar (já que lgamma(x+1)na verdade retorna , exatamente o que ele está tentando aproximar - mal - via aproximação de Stirling).registro(x!)

Da mesma forma, não sei por que o autor não usa a choosefunção interna na primeira parte, uma função que vem na distribuição padrão de R. Nesse caso, a função de distribuição relevante provavelmente também está embutida.

Você realmente não precisa de dois casos separados; a lgammaum funciona muito bem para a direita até os menores valores. Por outro lado, a choosefunção funciona para valores bastante grandes (por exemplo, choose(1000,500)funciona muito bem). O mais seguro opção é, provavelmente lgamma, embora você precisa ter muito grande e antes era um problema.xy

Com mais informações, deve ser possível identificar a fonte do teste. Meu palpite é que o escritor o tirou de algum lugar, portanto deve ser possível localizá-lo. Você tem algum contexto para isso?

Quando você diz "otimizar", você quer torná-lo mais rápido, mais curto, mais sustentável ou algo mais?


Edite após ler rapidamente sobre o papel:

Os autores parecem estar errados em vários pontos. O teste exato de Fisher não pressupõe que as margens sejam fixas, simplesmente condiciona -as, o que não é a mesma coisa, como discutido, por exemplo, aqui , com referências. De fato, eles parecem completamente ignorantes do debate sobre condicionamento nas margens e por que isso é feito. Vale a pena ler os links de lá.

[Eles procedem do 'teste de Fisher é sempre mais conservador que o nosso', à afirmação de que o teste de Fisher é muito conservador ... o que não segue necessariamente, a menos que esteja errado na condição . Eles teriam que estabelecer isso, mas, como é algo que os estatísticos discutem há cerca de 80 anos, e esses autores não sabem por que o condicionamento é feito, acho que esses caras não chegaram ao fundo dessa questão. .]

Os autores do artigo parecem pelo menos entender que as probabilidades que elas dão devem ser acumuladas para dar valores-p; por exemplo, próximo ao meio da primeira coluna da página 5 (ênfase minha):

A significância estatística de acordo com o teste exato de Fisher para esse resultado é de 4,6% (valor P bicaudal, ou seja, a probabilidade de ocorrência dessa tabela na hipótese de que as frequências EST da actina sejam independentes das bibliotecas de cDNA). Em comparação, o valor P calculado a partir da forma cumulativa (Equação 9, consulte Métodos) da Equação 2 (ou seja, para que a frequência relativa de ESTs de actina seja a mesma em ambas as bibliotecas, dado que pelo menos 11 ESTs cognatos são observados em a biblioteca do fígado depois de duas foram observadas na biblioteca do cérebro) é de 1,6%.

(embora eu não tenha certeza se concordo com o cálculo do valor ali; teria que verificar cuidadosamente para ver o que eles estão realmente fazendo com a outra extremidade.)

Eu não acho que o programa faça isso.

Cuidado, porém, que a análise deles não é um teste binomial padrão; eles usam um argumento bayesiano para derivar um valor-p em um teste caso contrário freqüentista. Eles também parecem - um tanto estranhamente, na minha opinião - condicionar , ao invés de . Isso significa que eles devem terminar com algo como um binômio negativo, e não um binômio, mas acho o artigo muito mal organizado e muito mal explicado (e estou acostumado a descobrir o que está acontecendo nos artigos de estatística), por isso estou não vou ter certeza, a menos que eu passe com cuidado.xx+y

Não estou nem convencido de que a soma de suas probabilidades seja 1 neste momento.

Há muito mais a ser dito aqui, mas a questão não é sobre o documento, é sobre a implementação no programa.

-

De qualquer forma, o resultado é que, pelo menos, o artigo identifica corretamente que os valores de p consistem em uma soma de probabilidades como as da equação 2, mas o programa não . (Veja as equações 9a e 9b na seção Métodos do documento.)

O código está simplesmente errado nisso.

[Você pode usar pbinom, como o comentário do @ whuber sugere, para calcular as probabilidades individuais (mas não a cauda, ​​já que não é um teste binomial conforme a estrutura), mas há um fator extra de 1/2 na equação 2, para que se você deseja replicar os resultados no documento, é necessário alterá-los.]

Você pode obtê-lo, com algumas brincadeiras, de pnbinom-

As formas usuais do binômio negativo são o número de tentativas para o sucesso ou o número de falhas para o sucesso . Os dois são equivalentes; A Wikipedia fornece a segunda forma aqui . A função de probabilidade é:kthkth

(k+r-1 1k)(1 1-p)rpk,

A equação 2 em p4 (e portanto também a Equação 1 em p3) é um binomial negativo, mas deslocado por 1. Seja , e .p=N1 1/(N1 1+N2)k=xr=y+1 1

Isso me preocupa porque, como os limites de não foram alterados de maneira semelhante, suas probabilidades podem nem aumentar 1.y

Isso seria ruim.

Glen_b -Reinstate Monica
fonte
11
+1 boa explicação. Existem alguns problemas adicionais com este código. É desnecessário calcular p2; o menor de p1e p2corresponde ao menor de xe y, respectivamente - isso é uma ineficiência. Um possível bug é que o segundo ramo da condicional falha ao calcular p2e usa apenas p1. Também estou desconfiado de que o código pode ser totalmente errônea, porque ele não aparece para calcular um valor p: é apenas a meio uma probabilidade binomial e, talvez, deveria ser uma cauda de probabilidade. Por que não usar pbinom/ dbinome acabar com isso?
whuber
Obrigado pela ótima resposta, fui capaz de rastrear a fonte da fórmula: genome.cshlp.org/content/7/10/986.short Eu queria alterá-lo para que fosse mais rápido e fácil de manter / ler.
yingw 18/01
Obrigado pelo artigo; foi útil para descobrir o que estava acontecendo no código. Que shemozzle.
Glen_b -Reinstala Monica
11
+1. Este é um post que não deve ser um wiki da comunidade! Eu acho que é devido às 14 rotações, mas neste caso, são todos por você. Sua diligência foi punida!
Darren Cook
Obrigado pelo voto de confiança. Sim, eu continuava voltando e fazendo melhorias enquanto lia o artigo, mas acho que é minha culpa parcialmente por não alcançar o resultado final com mais eficiência.
Glen_b -Replica Monica