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

ara*_*ame 31 precision r r-faq

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

a <- 1:10
b <- 100:110
t.test(a,b) 
Run Code Online (Sandbox Code Playgroud)

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

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

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

谢谢你的帮助,抱歉这个曲折的问题.

Ben*_*ker 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
Run Code Online (Sandbox Code Playgroud)

其次,当我在组之间做出更大的差异时,我确实得到了@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
Run Code Online (Sandbox Code Playgroud)

打印输出的行为t.test是由它的调用驱动的stats:::print.htest(它也被其他统计测试函数调用chisq.test,如OP所指出的),而这些函数又调用format.pval,它表示p值小于其值eps(即.Machine$double.eps默认情况下)< eps.我很惊讶地发现自己不同意这些一般敏锐的评论者......

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


42-*_*42- 13

两个问题:

1)在1e-16和1e-32的p值之间存在统计学意义的可能差异?如果你真的可以证明它是正确的,那么使用记录的值是要走的路.

2)当你对R的数值精度感兴趣时,为什么要使用维基百科?

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

> .Machine$double.eps
[1] 2.220446e-16
Run Code Online (Sandbox Code Playgroud)

在[0,1]范围内解释时,该数字实际上为零

  • 你假设p值为0.05就足以满足我的应用需求,并且它不适用于许多应用程序.例如,在本文的抽象被给予的Bonferroni校正〜1E-10的p值:http://www.plosgenetics.org/article/info%3Adoi%2F10.1371%2Fjournal.pgen.1002215 (3认同)
  • 最后的评论并不严格.`.Machine $ double.xmin`(在我的机器上为2.22e-308)是可以与零区分开的最小数字; `.Machine $ double.eps`是最小的数字,这样`1 + x`可以与1区分开来...... (3认同)
  • 1)当做很多bonferroni修正时,知道真实的数字并不仅仅是"它很小"是有帮助的. (2认同)
  • 啊,一个消费意义战略.我怀疑Bonferroni对于大小为23-16的多次校正的数量是否准确到0.05.那将是4.166667e + 13比较. (2认同)

Ric*_*ton 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)
Run Code Online (Sandbox Code Playgroud)

你在评论中提到你想做bonferroni修正.我建议您使用p.adjust(your_p_value, method = "bonferroni")而不是为此编制自己的代码. pairwise.t.test用这个.


eWi*_*dII 7

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

  • 这是错的.正如DWin在他的回答中提到的那样,由于处理浮点数的方式,`2.2e-16`是大于零的最小数,可以存储(在大多数系统上).它没有更准确地存储. (6认同)
  • 抱歉,我的评论中含糊不清的语言.`2.2e-16`实际上是最小的`x` st`1 + x!= x`,它松散地翻译为"你能够准确区分数字".您可以表示较小的数字(请参阅`.Machine $ double.xmin`)但精度较低. (6认同)
  • 看到我的回答:我认为你是对的,虽然我的回答确实提供了一些额外的信息.我给了你+1来抵消负面评价.我们可以看看其他评论者是否仍然不同意...... (3认同)
  • 我完全误解了OP的问题,并根据Ben的答案和聊天讨论,我应该道歉并撤消我的downvote(因此编辑,所以我可以解锁我的投票). (3认同)
  • 这在理论上可能是错误的另一个原因是,建议的使用是在基因测试中最可能计数的t.test(唯一可能的"4e13"测试有意义的域)将应用正态理论测试错误的数据类型. (2认同)

use*_*593 5

一些 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
Run Code Online (Sandbox Code Playgroud)

[1] 3.819961e-294