我responding在Reddit AskScience处提出质疑,我在runif()
的功能方面遇到了一些奇怪的问题。我试图统一采样从1到52的集合。我的第一个想法是使用runif():
as.integer(runif(n, min = 1, max = 52))
但是,我发现该操作从未产生52的值。例如:
length(unique(as.integer(runif(1000000, 1, 52))))
[1] 51
就我的目的而言,我只是转向sample()
:
sample(52, n, replace = TRUE)
在runif()文档中说明:
runif不会生成任何一个极值,除非max = min或max-min与min相比较小,特别是不适用于默认参数。
我想知道为什么runif()
以这种方式行事。它似乎应该能够产生极端的价值观。如果它试图统一生成样本,则从集合中。这是一个功能,为什么?
答案 0 :(得分:13)
这确实是一个特色。 runif
的{{3}}包含以下C代码:
/* This is true of all builtin generators, but protect against
user-supplied ones */
do {u = unif_rand();} while (u <= 0 || u >= 1);
return a + (b - a) * u;
这意味着unif_rand()
可能返回0或1,但runif()
被设计为跳过那些(不太可能)的情况。
我的猜测是这样做是为了保护在边缘情况下失败的用户代码(值完全在范围的边界上)。
此功能为C source code(从评论中可以看出0<u<1
自动生成内置统一生成器,但对于用户提供的生成器可能不适用。)
sample(1:52,size=n,replace=TRUE)
是实现目标的惯用方法(虽然不一定是最有效的方式)。
答案 1 :(得分:3)
as.integer
的作用类似于trunc
。它将通过将给定值截断为0来形成整数。由于值不能超过52(see Ben's answer),它们将始终被截断为1到51之间的值。
您会在floor
(或ceiling
)中看到不同的结果。 请注意,您必须通过添加max
来调整runif
1
(如果是min
,则调整ceiling
)。同样请注意,在这种情况下,由于min
和max
都高于0,您可以将floor
替换为trunc
或{{1}也是。
as.integer
答案 2 :(得分:2)
as.integer(51.999)
51
这是因为as.integer如何工作。
如果要从离散分布中绘制,请使用样本。 runif
不适用于离散分发。