我想找到使用R的大型n
的所有可能排列。目前我使用permutations(n,n)
包中的gtools
,但对于n>10
,这几乎是不可能的;由于大量的排列(n!),我得到内存崩溃。我不想抽样,因为我需要找到特定统计数据的确切分布。有什么办法可以让我更快地做到这一点,或者我可以把它分解成小块?
答案 0 :(得分:6)
你的目标很可能是不切实际的(“大n”有多大?即使你可以产生大量的排列,你需要花多长时间来总结它们?对于十亿个元素的详尽计算和一千万个元素的随机样本之间是否存在准确性?)。但是:
iterpc
包可以枚举块中的排列。例如:
library("iterpc")
设置一个对象(“迭代器”)以生成10个对象的排列:
I <- iterpc(10,labels=1:10,ordered=TRUE)
返回前5个排列:
getnext(I,5)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 2 3 4 5 6 7 8 9 10
## [2,] 1 2 3 4 5 6 7 8 10 9
## [3,] 1 2 3 4 5 6 7 9 8 10
## [4,] 1 2 3 4 5 6 7 9 10 8
## [5,] 1 2 3 4 5 6 7 10 8 9
返回接下来的5个排列:
getnext(I,5)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 2 3 4 5 6 7 10 9 8
## [2,] 1 2 3 4 5 6 8 7 9 10
## [3,] 1 2 3 4 5 6 8 7 10 9
## [4,] 1 2 3 4 5 6 8 9 7 10
## [5,] 1 2 3 4 5 6 8 9 10 7
假设您可以一次计算一个块的统计数据然后合并结果,这应该是可行的。看起来你看起来并不容易并行化:没有办法跳转到迭代器的特定元素...... numperm
包中的sna
函数提供“随机”(即非顺序访问排列,虽然排序与iterpc
给出的顺序不同 - 但我猜测iterpc
的效率要高得多,所以你可能会更好地依次对块进行处理单个节点/核心/机器,而不是分发流程。
以下是sna::numperm
给出的前5个排列:
library("sna")
t(sapply(1:5,numperm,olength=10))
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 2 1 3 4 5 6 7 8 9 10
## [2,] 2 3 1 4 5 6 7 8 9 10
## [3,] 2 3 4 1 5 6 7 8 9 10
## [4,] 2 3 4 5 1 6 7 8 9 10
## [5,] 2 3 4 5 6 1 7 8 9 10
iterpc
的内容是用C ++编写的,所以它应该非常高效,但无论哪种事情都会变得更难以获得更大的n
值。令我惊讶的是,iterpc
可以毫不费力地处理完整的10!= 3628800排列:
system.time(g <- getall(I))
## user system elapsed
## 0.416 0.304 0.719
dim(g)
## [1] 3628800 10
但是,我无法在我的机器上的单个块中使用n>10
进行任何计算(n = 11:"cannot allocate vector of size 1.6 Gb"
... n&gt; 11 "The length of the iterator is too large, try using getnext(I,d)"
)