我想要做的是在给定特定样本大小的情况下生成1和0的所有可能排列。例如,对于n = 8的样本,我希望m = 2 ^ 8 = 256种可能的排列,即:
我在R中编写了一个函数来执行此操作,但是在n = 11之后需要很长时间才能运行。我更喜欢R中的解决方案,但如果它在另一种编程语言中,我可能会想出来。谢谢!
PermBinary <- function(n){
n.perms <- 2^n
array <- matrix(0,nrow=n,ncol=n.perms)
# array <- big.matrix(n, n.perms, type='integer', init=-5)
for(i in 1:n){
div.length <- ncol(array)/(2^i)
div.num <- ncol(array)/div.length
end <- 0
while(end!=ncol(array)){
end <- end +1
start <- end + div.length
end <- start + div.length -1
array[i,start:end] <- 1
}
}
return(array)
}
答案 0 :(得分:4)
expand.grid
可能是获得你想要的最佳工具。
例如,如果您希望样本大小为3,我们可以执行类似
的操作expand.grid(0:1, 0:1, 0:1)
样本量为4
expand.grid(0:1, 0:1, 0:1, 0:1)
所以我们想要做的就是找到一种自动化调用的方法。
如果我们有一个我们想要提供给expand.grid
的输入列表,我们可以使用do.call
为我们构建调用。例如
vals <- 0:1
tmp <- list(vals, vals, vals)
do.call(expand.grid, tmp)
所以现在的挑战是自动制作上面的“tmp”列表,我们可以决定我们想要多少份“vals”。有很多方法可以做到这一点,但一种方法是使用replicate
。由于我们需要一个列表,我们需要告诉它不要简化结果,否则我们将得到一个矩阵/数组作为结果。
vals <- 0:1
tmp <- replicate(4, vals, simplify = FALSE)
do.call(expand.grid, tmp)
或者我们可以在列表输入上使用rep
(我认为它更快,因为它没有复制的开销,但我没有测试过它)
tmp <- rep(list(vals), 4)
do.call(expand.grid, tmp)
现在将其包装成一个函数来获取:
binarypermutations <- function(n, vals = 0:1){
tmp <- rep(list(vals), n)
do.call(expand.grid, tmp)
}
然后调用样本大小,如binarypermutations(5)
。
这样就得到了一个尺寸为2 ^ n x n的data.frame - 如果您愿意,可以转置并转换为不同的数据类型。
答案 1 :(得分:3)
上面的答案可能会更好,因为它使用base
- 我的第一个想法是使用data.table的CJ
函数:
library(data.table)
do.call(CJ, replicate(8, c(0, 1), FALSE))
它会比expand.grid稍微快一些(~15%),所以它对于极端情况只会更有价值。