我之前问过以下问题 Permutation of n bernoulli random variables in R
只要n相对较小(<30),此问题的答案就很有效,否则会出现以下错误代码错误:无法分配大小为4.0 Gb的向量。通过在工作中使用桌面,我可以使代码以更大的值运行,但最终会出现相同的错误。即使对于我的计算机可以处理的值(例如25),代码也非常慢。
此代码的目的是计算精确分布的CDF(因此发生排列)与正态近似值之间的差。我随机生成一些数据,计算测试统计量,然后我需要通过将所有导致较小的测试统计量值除以排列总数的排列求和来确定CDF。
我的想法是一次只生成一个排列列表,请注意它是否小于我的观察值,然后继续执行下一个,即遍历所有可能的排列,但是我不能只拥有循环遍历所有排列的数据帧,因为那样会导致大小和速度完全相同。
长话短说:我需要为n个bernoulli试验生成1和0的所有可能排列,但是我需要一次执行一次,以便全部生成,并且对于任意n都不会生成一次以上。对于n = 3,2 ^ 3 = 8,我首先生成
000
计算我的测试统计数据是否大于(1或0),然后生成
001
再次计算,然后生成
010
计算,然后生成
100
计算,然后生成
011
等到111
我很好,这是一个遍历2 ^ n的循环,它在循环的每一步都输出排列,但不会将它们全部保存在某个地方。同样,我也不关心它们的生成顺序,上面只是我手工完成这些操作的方式。
此外,如果仍然可以加快以前的代码的速度,那也将有所帮助。
答案 0 :(得分:2)
迭代器是解决您的问题的一个好方法。有一个名为arrangements
的程序包,它能够以迭代方式生成排列。观察:
library(arrangements)
# initialize iterator
iperm <- ipermutations(0:1, 3, replace = T)
for (i in 1:(2^3)) {
print(iperm$getnext())
}
[1] 0 0 0
[1] 0 0 1
.
.
.
[1] 1 1 1
它是用C
编写的,非常有效。您还可以一次生成m
个排列,如下所示:
iperm$getnext(m)
由于下一个排列是由C
中的for循环而不是R
中的for循环生成的,因此可以提供更好的性能。
如果您确实需要提高性能,可以使用parallel
软件包。
iperm <- ipermutations(0:1, 40, replace = T)
parallel::mclapply(1:100, function(x) {
myPerms <- iperm$getnext(10000)
# do something
}, mc.cores = parallel::detectCores() - 1)
注意:所有代码都未经测试。