web-dev-qa-db-fra.com

Pourquoi ne puis-je pas obtenir une valeur de p inférieure à 2,2e-16?

J'ai trouvé ce problème avec les tests t et le chi carré dans R, mais je suppose que ce problème s'applique généralement aux autres tests. Si je fais:

a <- 1:10
b <- 100:110
t.test(a,b) 

Je reçois: t = -64.6472, df = 18.998, p-value < 2.2e-16. Je sais d'après les commentaires que 2.2e-16 est la valeur de .Machine$double.eps - le plus petit nombre à virgule flottante tel que 1 + x != 1, mais bien sûr, R peut représenter des nombres beaucoup plus petits que cela. Je sais aussi par le R FAQ que R doit arrondir les flottants à une précision de 53 chiffres binaires: R FAQ .

Quelques questions: (1) ai-je raison de lire que 53 chiffres binaires de précision ou sont des valeurs dans R < .Machine$double.eps pas calculé avec précision? (2) Pourquoi, lors de ces calculs, R ne fournit-il pas un moyen d'afficher une valeur plus petite pour la valeur p, même avec une certaine perte de précision? (3) Existe-t-il un moyen d'afficher une valeur de p plus petite, même si je perds de la précision? Pour un seul test, 2 chiffres décimaux significatifs conviendraient, pour les valeurs que je vais corriger à Bonferroni, j'en aurai besoin de plus. Quand je dis "perdre de la précision", je pense que <53 chiffres binaires, mais (4) je me trompe complètement et toute valeur de p < .Machine$double.eps est extrêmement inexact? (5) Est-ce que R est juste honnête et les autres packages de statistiques ne le sont pas?

Dans mon domaine, de très petites valeurs de p sont la norme, quelques exemples: http://www.ncbi.nlm.nih.gov/pubmed/20154341 , http: // www. plosgenetics.org/article/info%3Adoi%2F10.1371%2Fjournal.pgen.1002215 et c'est pourquoi je veux représenter de si petites valeurs de p.

Merci pour votre aide, désolé pour une question aussi tortueuse.

32

Essayez quelque chose comme ceci t.test(a,b)$p.value voyez si cela vous donne la précision dont vous avez besoin. Je crois que cela a plus à voir avec l'impression du résultat qu'avec la valeur réelle stockée de l'ordinateur qui devrait avoir la précision nécessaire.

7
eWizardII

Je suis perplexe par plusieurs choses dans l'échange de réponses et de commentaires ici.

Tout d'abord, lorsque j'essaie l'exemple original de l'OP, je n'obtiens pas une valeur p aussi petite que celles qui sont débattues ici (plusieurs versions 2.13.x et R-devel différentes):

a <- 1:10
b <- 10:20
t.test(a,b)
## data:  a and b 
## t = -6.862, df = 18.998, p-value = 1.513e-06

Deuxièmement, lorsque je fais beaucoup plus de différence entre les groupes, j'obtiens en fait les résultats suggérés par @eWizardII:

a <- 1:10
b <- 110:120
(t1 <- t.test(a,b))
# data:  a and b 
# t = -79.0935, df = 18.998, p-value < 2.2e-16
#
> t1$p.value
[1] 2.138461e-25

Le comportement de la sortie imprimée dans t.test est motivé par son appel à stats:::print.htest (qui est également appelé par d'autres fonctions de test statistique telles que chisq.test, comme le fait remarquer l'OP), qui à son tour appelle format.pval, qui présente p valeurs inférieures à sa valeur de eps (qui est .Machine$double.eps par défaut) comme < eps. Je suis surpris de me retrouver en désaccord avec des commentateurs généralement aussi astucieux ...

Enfin, bien qu'il semble stupide de s'inquiéter de la valeur précise d'une très petite valeur p, l'OP a raison de dire que ces valeurs sont souvent utilisées comme indices de force probante dans la littérature bioinformatique - par exemple , on pourrait tester 100 000 gènes candidats et regarder la distribution des valeurs p résultantes (rechercher "tracé volcanique" pour un exemple de ce type de procédure).

20
Ben Bolker

Deux questions:

1) Quelle différence possible dans l'implication statistique y aurait-il entre les valeurs de p de 1e-16 et 1e-32? Si vous pouvez vraiment le justifier, l'utilisation des valeurs enregistrées est la solution.

2) Pourquoi utilisez-vous Wikipedia lorsque vous vous intéressez à la précision numérique de R?

La R-FAQ indique que "les autres nombres [qui ne sont pas des nombres entiers] doivent être arrondis à (généralement) une précision de 53 chiffres binaires." 16 chiffres est à peu près la limite. Voici comment obtenir les limites de précision lorsque vous êtes sur la console:

> .Machine$double.eps
[1] 2.220446e-16

Ce nombre est effectivement nul lorsqu'il est interprété sur une plage de [0,1]

13
42-

La page Wikipedia à laquelle vous avez lié était pour le type Decimal64 que R n'utilise pas - il utilise des doubles standard.

Tout d'abord, quelques définitions de la page d'aide .Machine.

double.eps: le plus petit nombre à virgule flottante positif "x" tel que "1 + x! = 1". ... Normalement "2.220446e-16".

double.xmin: le plus petit nombre à virgule flottante normalisé non nul ... Normalement "2,225074e-308".

Vous pouvez donc représenter des nombres inférieurs à 2,2e-16, mais leur précision est diminuée et cela pose des problèmes de calculs. Essayez quelques exemples avec des nombres proches de la plus petite valeur représentable.

2e-350 - 1e-350
sqrt(1e-350)

Vous avez mentionné dans un commentaire que vous vouliez faire des corrections bonferroni. Plutôt que de rouler votre propre code pour cela, je vous suggère d'utiliser p.adjust(your_p_value, method = "bonferroni") à la place. pairwise.t.test L'utilise.

9
Richie Cotton

Certains packages R résolvent ce problème. Le meilleur moyen est d'utiliser le package pspearman.

source("http://www.bioconductor.org/biocLite.R")
biocLite("pspearman")
library("pspearman")
a=c(1:110,110)
b=1:111
out <- spearman.test(a, b, alternative = "greater", approximation="t-distribution")
out$p.value

[1] 3,819961e-294

4
user1277593

Récemment eu le même problème. Un autre statisticien recommande:

A <- cor.test(…)
p <- 2* pt(A$statistic,  df = A$parameter, lower.tail=FALSE)
2
Vince