Chase 提供了一个很好的答案,并提到了 while() 迭代失控的问题。失控的while() 的问题之一是,如果您一次进行一次试验,并且需要多次试验,比如 t,才能找到与 @ 的目标数量相匹配的试验。 987654323@s,您会产生 t 调用 main 函数的开销,在这种情况下为 rbinom()。
但是有一条出路,因为rbinom(),就像 R 中的所有这些(伪)随机数生成器一样,是矢量化的,我们可以一次生成 m 个试验并检查那些m 试验以符合 5 1s 的要求。如果没有找到,我们会反复进行 m 次试验,直到找到符合要求的试验。这个想法在下面的函数foo() 中实现。 chunkSize 参数是 m,即一次要绘制的试验次数。我还借此机会允许该函数查找多个保形试验;参数n 控制要返回多少保形试验。
foo <- function(probs, target, n = 1, chunkSize = 100) {
len <- length(probs)
out <- matrix(ncol = len, nrow = 0) ## return object
## draw chunkSize trials
trial <- matrix(rbinom(len * chunkSize, 1, probs),
ncol = len, byrow = TRUE)
rs <- rowSums(trial) ## How manys `1`s
ok <- which(rs == 5L) ## which meet the `target`
found <- length(ok) ## how many meet the target
if(found > 0) ## if we found some, add them to out
out <- rbind(out,
trial[ok, , drop = FALSE][seq_len(min(n,found)), ,
drop = FALSE])
## if we haven't found enough, repeat the whole thing until we do
while(found < n) {
trial <- matrix(rbinom(len * chunkSize, 1, probs),
ncol = len, byrow = TRUE)
rs <- rowSums(trial)
ok <- which(rs == 5L)
New <- length(ok)
if(New > 0) {
found <- found + New
out <- rbind(out, trial[ok, , drop = FALSE][seq_len(min(n, New)), ,
drop = FALSE])
}
}
if(n == 1L) ## comment this, and
out <- drop(out) ## this if you don't want dimension dropping
out
}
它是这样工作的:
> set.seed(1)
> foo(probs, target = 5)
[1] 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0
[31] 0
> foo(probs, target = 5, n = 2)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 0 0 0 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0 0 0 1
[,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21]
[1,] 0 0 0 1 1 0 0 0 0 0
[2,] 0 1 0 0 1 0 0 0 0 0
[,22] [,23] [,24] [,25] [,26] [,27] [,28] [,29] [,30] [,31]
[1,] 1 0 1 0 0 0 1 0 0 0
[2,] 1 0 1 0 0 0 0 0 0 0
请注意,我在n == 1 的情况下删除了空维度。如果您不想要此功能,请将最后一个 if 代码块注释掉。
您需要平衡chunkSize 的大小和一次检查这么多试验的计算负担。如果要求(这里是 5 个1s)不太可能,那么增加chunkSize 以便减少对rbinom() 的调用。如果可能需要,那么如果您只想要一两个,则一次很少有点画试验和大chunkSize,因为您必须评估每个试画。