我有一个包含36个元素的向量V,其中18为“ 0”,而18为“ 1”。 我想计算此向量的N个随机(而不是前N个)排列。
我可以这样做:
library(combinat)
N <- 100 # or 200, 300, 500... max 1000
V <- c(rep(0, 18), rep(1, 18))
n <- factorial(36) # total number of unique possible permutations
p <- unique(permn(V))[sample(1:n, N)]
但是我很快遇到了组合爆炸问题,因为
sample(1:n, N)
返回Error in 1:n : result would be too long a vector
和
permn(V)
返回Error in vector("list", gamma(n + 1)) : vector size specified is too large
还有另一种(更好)的方法吗?
答案 0 :(得分:6)
首先,由于元素重复,因此没有factorial(36)
结果。如果这样做,要获取总数,我们可以使用gmp
包来获取:
gmp::factorialZ(36)
Big Integer ('bigz') :
[1] 371993326789901217467999448150835200000000
我们实际上处理的是 multisets 的排列(正如@JakubBucek在评论中指出的那样)。使用软件包RcppAlgos
(我编写的)或软件包arrangements
,我们可以轻松,正确地计算结果总数,更重要的是生成所需的结果。
首先,实际结果数:
arrangements::npermutations(0:1, freq = c(18, 18), bigz = TRUE)
Big Integer ('bigz') :
[1] 9075135300
RcppAlgos::permuteCount(0:1, freqs = c(18, 18))
[1] 9075135300
这是组合技术的结果。也就是说,我们必须除以相似元素排列数量的乘积:
gmp::factorialZ(36) / gmp::pow.bigz(gmp::factorialZ(18), 2)
Big Rational ('bigq') :
[1] 9075135300
现在,生成您的随机排列。对于包arrangements
,我们使用nsample
参数。此外,我们可以设置可重复性的种子:
set.seed(123)
r1 <- arrangements::permutations(0:1, freq = c(18, 18), nsample = 10)
set.seed(123)
r2 <- arrangements::permutations(0:1, freq = c(18, 18), nsample = 10)
dim(r1)
[1] 10 36
identical(r1, r2)
[1] TRUE
## only showing 10 columns
head(r1[,1:10])
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 1 1 0 1 1 1
[2,] 1 0 1 1 1 1 1 1 1 0
[3,] 0 0 0 0 0 1 1 0 0 0
[4,] 1 1 1 0 0 1 0 1 0 0
[5,] 0 1 1 0 0 1 1 1 0 1
[6,] 0 0 0 1 1 1 0 1 1 1
对于RcppAlgos
,我们使用类似的参数permuteSample
和n
来调用seed
:
r3 <- RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 10, seed = 42)
r4 <- RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 10, seed = 42)
identical(r3, r4)
[1] TRUE
dim(r3)
[1] 10 36
两个软件包也非常有效。不到1000秒即可生成1000个随机排列:
system.time(RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 1000))
user system elapsed
0.051 0.000 0.052
system.time(arrangements::permutations(0:1, freq = c(18, 18), nsample = 1000))
user system elapsed
0.249 0.000 0.249
答案 1 :(得分:2)
@Joseph Wood得到了完美的答案。以防万一,您需要使用这些采样排列的列表:
r <- RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 100)
r <- lapply(1:dim(r)[1], function(x) {r[x,]})