【发布时间】:2018-02-27 09:24:42
【问题描述】:
我希望在 R 中生成所有可能的长度为 n 的二进制向量。执行此操作的最佳方法是什么(最好是计算高效且可读的代码)?
【问题讨论】:
我希望在 R 中生成所有可能的长度为 n 的二进制向量。执行此操作的最佳方法是什么(最好是计算高效且可读的代码)?
【问题讨论】:
n = 3
expand.grid(replicate(n, 0:1, simplify = FALSE))
# Var1 Var2 Var3
#1 0 0 0
#2 1 0 0
#3 0 1 0
#4 1 1 0
#5 0 0 1
#6 1 0 1
#7 0 1 1
#8 1 1 1
【讨论】:
受this question 生成所有可能的长度为n 且包含小于 m 1s 的二进制向量的启发,我扩展了此代码以生成所有可能的组合。不过,它并不漂亮。
> z <- 3
> z <- rep(0, n)
> do.call(rbind, lapply(0:n, function(i) t(apply(combn(1:n,i), 2, function(k) {z[k]=1;z}))))
[,1] [,2] [,3]
[1,] 0 0 0
[2,] 1 0 0
[3,] 0 1 0
[4,] 0 0 1
[5,] 1 1 0
[6,] 1 0 1
[7,] 0 1 1
[8,] 1 1 1
它在做什么?一旦我们把它剥离,这个单线的核心如下:
apply(combn(1:n,i), 2, function(k) {z[k]=1;z})
要理解这一点,让我们再退一步。函数combn(x,m) 一次生成x 和m 的所有可能组合。
> combn(1:n, 1)
[,1] [,2] [,3]
[1,] 1 2 3
> combn(1:n, 2)
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 2 3 3
> combn(1:n, 3)
[,1]
[1,] 1
[2,] 2
[3,] 3
为了使用apply(MARGIN=2),我们一次将这个函数的一列传递给我们的内部函数function(k) {z[k]=1;z},它简单地将索引k处的所有值替换为1。由于它们最初都是0,这给了我们每个可能的二进制向量。
剩下的只是装点门面。 combn 给了我们一个宽而短的矩阵;我们用t 转置它。 lapply 返回一个列表;我们将列表的每个元素中的矩阵与do.call(rbind, .) 绑定在一起。
【讨论】:
您应该定义什么是“最佳方式”(最快?最短的代码?等等)。
一种方法是使用包R.utils 和函数intToBin 将十进制数转换为二进制数。请参阅示例。
require(R.utils)
n <- 5
strsplit(intToBin(0:(2 ^ n - 1)), split = "")
【讨论】: