为何pbinom()中np的微小舍入误差会导致计算出的p值偏差较大?
我编写了一个计算二项分布概率的函数,用户可输入样本概率。比如用户输入35次试验中成功25次对应的0.7143,我将该概率乘以样本量得到分位数,再用pbinom()计算。但两种计算方式(用非整数分位数vs整数分位数)的结果差异极大:
> 2*pbinom(.7143*35,35,.5,lower.tail = FALSE)+dbinom(.7143*35,35,.5) [1] 0.005988121 Warning message: In dbinom(0.7143 * 35, 35, 0.5) : non-integer x = 25.000500 > 2*pbinom(25,35,.5,lower.tail = FALSE)+dbinom(25,35,.5) [1] 0.01133098
尾部的差异可能导致统计结论不同。再看远离尾部的例子(35次试验成功18次):
> 2*pbinom(.5143*35,35,.5,lower.tail = FALSE)+dbinom(.5143*35,35,.5) [1] 0.7358788 Warning message: In dbinom(0.5143 * 35, 35, 0.5) : non-integer x = 18.000500 > 2*pbinom(18,35,.5,lower.tail = FALSE)+dbinom(18,35,.5) [1] 0.8679394
p值差异达13%。我知道警告是因为非整数x,也可以用舍入解决,但为什么分位数仅0.0005的微小误差,会导致p值偏差这么大?
问题根源
核心原因在于离散分布的特性和你用到的两个函数的行为:
dbinom()对非整数输入返回0
二项分布是离散概率分布,只有当成功次数为整数时,概率才不为0。你传入的25.0005、18.0005都是非整数,dbinom()直接返回0——这不是函数bug,是离散分布的本质决定的。你的p值计算逻辑放大了这个差异
你的计算公式是2*pbinom(..., lower.tail=FALSE) + dbinom(...),这个逻辑是要把观测点的概率和双侧尾部概率加起来:- 用整数25时:
dbinom(25,35,.5)返回X=25的真实概率(约0.0053),这部分被加到了结果里; - 用25.0005时:
dbinom()返回0,相当于直接漏掉了X=25这个点的概率。
看数值就能验证:第一个例子里两个结果的差值(0.0113-0.00599≈0.0053),正好等于
dbinom(25,35,.5)的结果;第二个例子的差值(0.8679-0.7359≈0.132),也正好是dbinom(18,35,.5)的结果。- 用整数25时:
尾部区域的单点概率占比更高
在分布尾部,单个整数点的概率在p值中占的比例更大,所以这种差异会更显眼——比如第一个例子里,漏掉的0.0053直接让p值几乎减半,很可能从“显著”变成“不显著”;而远离尾部的区域,单点概率占比相对小,但也能造成13%的差值。
内容的提问来源于stack exchange,提问作者Steven Ouellette

