为什么我不能得到小于2.2e-16的p值?

时间:2011-08-07 04:16:06

标签: r precision r-faq

我在R测试中发现了这个问题,但是我认为这个问题通常适用于其他测试。如果我这样做:

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

我得到:t = -64.6472, df = 18.998, p-value < 2.2e-16。我从评论中知道2.2e-16.Machine$double.eps的值 - 最小的浮点数,使1 + x != 1,但当然R可以表示比这小得多的数字。我也从R FAQ中知道R必须将浮点数舍入到53位二进制数字精度:R FAQ

一些问题:(1)我是否正确地读到精度的53个二进制数字或R < .Machine$double.eps中的值未准确计算? (2)为什么在进行这样的计算时,R不提供显示p值较小值的方法,即使精度有所损失? (3)有没有办法显示较小的p值,即使我失去了一些精度?对于单个测试,2个十进制有效数字将是正常的,对于我将要更加正确的Bonferroni值,我需要更多。当我说“失去一些精确度”时,我认为&lt; 53个二进制数字,但是(4)我完全错了,任何p值< .Machine$double.eps都非常不准确? (5)R只是诚实而其他统计数据包不是吗?

在我的领域中,非常小的p值是常态,一些例子:http://www.ncbi.nlm.nih.gov/pubmed/20154341http://www.plosgenetics.org/article/info%3Adoi%2F10.1371%2Fjournal.pgen.1002215这就是我想要表示如此小的p值的原因。

感谢您的帮助,对于这样一个曲折的问题感到抱歉。

6 个答案:

答案 0 :(得分:20)

我在这里交换答案和评论的几件事情让我感到困惑。

首先,当我尝试OP的原始示例时,我没有得到 p 这么小的值(这里有几个不同的2.13.x版本和R-devel) ):

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

其次,当我将组之间的区别大得多时,我确实得到了@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

t.test中打印输出的行为是由其对stats:::print.htest的调用驱动的(如OP所述,其他统计测试函数也会调用chisq.test)反过来调用format.pval,其{em> p 值小于其值eps(默认为.Machine$double.eps)为< eps。我很惊讶地发现自己不同意这些普遍敏锐的评论者......

最后,虽然担心非常小的 p 值的确切值似乎很愚蠢,但OP是正确的,这些值通常被用作生物信息学文献中证据强度的指标 - - 例如,人们可能会测试100,000个候选基因,并查看结果 p 值的分布(搜索“火山图”这一过程的一个例子)。

答案 1 :(得分:13)

两个问题:

1)统计意义在1e-16和1e-32的p值之间可能存在哪些差异?如果你真的可以证明它的合理性,那么使用记录的值是可行的方法。

2)当你对R?

的数值准确性感兴趣时,为什么要使用维基百科?

R-FAQ说“其他[意思是非整数]数字必须四舍五入到(通常)53位二进制数字精度。” 16位数字是有限的。这是在控制台上获得精确度限制的方法:

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

当在[0,1]

的范围内进行解释时,该数字实际上为零

答案 2 :(得分:9)

您链接的维基百科页面是R不使用的Decimal64类型 - 它使用标准问题双打。

首先,.Machine帮助页面中的一些定义。

  

double.eps:最小的正浮点数'x'   '1 + x!= 1'。 ......通常是'2.220446e-16'。

     

double.xmin:最小的非零标准化浮点数   ......通常是'2.225074e-308'。

因此,您可以表示小于2.2e-16的数字,但它们的准确性会变暗,并且会导致计算出现问题。尝试一些数字接近最小可表示值的例子。

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

您在评论中提到您想要进行bonferroni更正。我建议您使用p.adjust(your_p_value, method = "bonferroni")而不是为此编制自己的代码。 pairwise.t.test使用此功能。

答案 3 :(得分:7)

尝试这样的事情t.test(a,b)$p.value看看它是否能为您提供所需的准确性。我认为它与结果的打印有关,而不是实际存储的计算机值,它应具有必要的精度。

答案 4 :(得分:4)

一些R包解决了这个问题。最好的方法是通过包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

答案 5 :(得分:2)

最近有同样的问题。统计员建议:

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