R中的种子行为与rbinom(prob = 0.5)不稳定

我发现当使用prob=0.5时, R的种子与rbinom()结合使用时,我会考虑不规则的行为(但我希望有一个简单的解释)。 总体思路:对我来说,如果我设置种子,运行rbinom()一次(即进行一个随机过程),尽pipe设置了什么样的prob值,随机种子应该改变一个增量。 然后,如果我再次将种子设置为相同的值,并运行另一个随机过程(如再次,如rbinom() ,但也许有不同的prob值),种子应该再次改变为相同的价值以前的单一随机过程。

我发现R只要我用任何prob!=0.5使用rbinom()就是这样做的。 这里是一个例子:

比较种子vector, .Random.seed和两个不同于0.5的概率:

 set.seed(234908) x <- rbinom(n=1,size=60,prob=0.4) temp1 <- .Random.seed set.seed(234908) x <- rbinom(n=1,size=60,prob=0.3) temp2 <- .Random.seed any(temp1!=temp2) > [1] FALSE 

比较种子向量, .Random.seed ,prob = 0.5与prob!= 0.5:

 set.seed(234908) x <- rbinom(n=1,size=60,prob=0.5) temp1 <- .Random.seed set.seed(234908) x <- rbinom(n=1,size=60,prob=0.3) temp2 <- .Random.seed any(temp1!=temp2) > [1] TRUE temp1==temp2 > [1] TRUE FALSE TRUE TRUE TRUE TRUE TRUE > [8] TRUE TRUE TRUE TRUE TRUE TRUE TRUE ... 

我已经find了对所有其他集合{0.1,0.2,…,0.9}的所有概率的prob=0.5比较。 同样的,如果我比较0.5以外{0.1,0.2,…,0.9}的prob值,那么.Random.seedvector总是一个一个地等于一个元素。 这些事实也适用于rbinom()奇数或偶数。

为了让它变得更奇怪(我很抱歉,这有点令人费解 – 这与我的函数的写法有关),当我使用保存为向量中的元素的概率时,如果0.5是第一个元素,第二。 这是这种情况下的例子:

第一种情况:0.5是向量中引用的第一个概率

 set.seed(234908) MNAR <- c(0.5,0.3) x <- rbinom(n=1,size=60,prob=MNAR[1]) y <- rbinom(n=1,size=50,prob=MNAR[2]) temp1 <- .Random.seed set.seed(234908) MNAR <- c(0.1,0.3) x <- rbinom(n=1,size=60,prob=MNAR[1]) y <- rbinom(n=1,size=50,prob=MNAR[2]) temp2 <- .Random.seed any(temp1!=temp2) > [1] TRUE any(temp1!=temp2) > [1] TRUE FALSE TRUE TRUE TRUE TRUE TRUE > [8] TRUE TRUE TRUE TRUE TRUE TRUE TRUE 

第二种情况:0.5是向量中引用的第二种概率

 set.seed(234908) MNAR <- c(0.3,0.5) x <- rbinom(n=1,size=60,prob=MNAR[1]) y <- rbinom(n=1,size=50,prob=MNAR[2]) temp1 <- .Random.seed set.seed(234908) MNAR <- c(0.1,0.3) x <- rbinom(n=1,size=60,prob=MNAR[1]) y <- rbinom(n=1,size=50,prob=MNAR[2]) temp2 <- .Random.seed any(temp1!=temp2) > [1] FALSE 

再次,我发现,尽pipe用于probsize的值,这种模式是成立的。 任何人都可以向我解释这个奥秘吗? 这导致了一个相当大的问题,因为结果应该是不一样的,因为种子出于某种原因在prob=0.5时使用/计算的方式不同,但在其他情况下是不一样的。

所以让我们把我们的意见变成一个答案。 感谢Ben Bolker为我们提供了一个链接到代码的正确轨道: https : unif_rand()和build议追踪unif_rand()被调用。

快速扫描,它似乎代码分为两个部分,由评论分隔:

 /*-------------------------- np = n*p >= 30 : ------------------- */ 

 /*---------------------- np = n*p < 30 : ------------------------- */ 

在每个内部,对unif_rand的调用unif_rand是不一样的(两次对一次)。

所以对于一个给定的sizen ),根据probp )的值,你的随机种子可能以不同的状态结束:不pipesize * prob >= 30

考虑到这一点,你用例子得到的所有结果现在应该是有意义的:

 # these end up in the same state rbinom(n=1,size=60,prob=0.4) # => np < 30 rbinom(n=1,size=60,prob=0.3) # => np < 30 # these don't rbinom(n=1,size=60,prob=0.5) # => np >= 30 rbinom(n=1,size=60,prob=0.3) # => np < 30 # these don't {rbinom(n=1,size=60,prob=0.5) # np >= 30 rbinom(n=1,size=50,prob=0.3)} # np < 30 {rbinom(n=1,size=60,prob=0.1) # np < 30 rbinom(n=1,size=50,prob=0.3)} # np < 30 # these do {rbinom(n=1,size=60,prob=0.3) # np < 30 rbinom(n=1,size=50,prob=0.5)} # np < 30 {rbinom(n=1,size=60,prob=0.1) # np < 30 rbinom(n=1,size=50,prob=0.3)} # np < 30 

我将在这个问题上采取逆向的立场,并声称预期不合适,不受文件支持。 该文档没有提出任何有关副作用(特别是.Random.seed )可以通过调用rbinom ,或者在各种情况下这些副作用可能会或可能不会相同的rbinom

rbinom有三个参数: nsizeprob 。 你的期望是,对于调用rbinom之前的随机种子集合, .Random.seed将在给定的nsizeprob 任何值(或者任何有限的sizeprob值)调用rbinom后是相同的。 你当然会意识到,不同的n值会有所不同。 rbinom并不保证或暗示。

不知道函数的内部,这是不可知的。 如另一个答案所示,基于sizeprob的乘积的algorithm是不同的。 而内部可能会改变,所以这些细节可能会改变。

至less在这种情况下,每次调用具有相同 nsize probrbinom后,得到的.Random.seed将是相同的。 我可以构build一个病理学的function,这是不正确的:

 seedtweak <- function() { if(floor(as.POSIXlt(Sys.time())$sec * 10) %% 2) { runif(1) } invisible(NULL) } 

基本上,这个函数看起来是十分之二的时间是奇数还是偶数来决定是否绘制一个随机数。 运行这个函数, .Random.seed可能会也可能不会改变:

 rs <- replicate(10, { set.seed(123) seedtweak() .Random.seed }) all(apply(rs, 1, function(x) Reduce(`==`, x))) 

你可以(应该)希望的最好的是,给定的一组代码与所有的input/参数相同(包括种子)将始终给出相同的结果。 只有大多数 (或只有一些)参数相同的情况下,预期相同的结果是不现实的,除非所有被调用的函数都做出这些保证。