R - 生成二进制向量的所有可能的成对组合

时间:2018-01-17 02:37:45

标签: r combinations combinatorics binary-data

我正在寻找一种智能方法来生成长度为n的两个向量的所有成对组合,其中只有一个值不为零。

现在我正在做一些非常绝望的事情,通过每个组合循环:n< - 3; z< - rep(0,n); m< - apply(combn(1:n,1),2,function(k){z [k] = 1; z}) 但是没有循环必须有更好的方法吗?

这就是我所追求的n = 3:

     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    1    0  

[1,]    1    0    0
[2,]    0    0    1

[1,]    0    1    0
[2,]    1    0    0

[1,]    0    1    0
[2,]    0    0    1

[1,]    0    0    1
[2,]    1    0    0

[1,]    0    0    1
[2,]    0    1    0

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

这样的东西?

n <- 3
g <- 2 # g must be < n 
m <- combn(n, g)
mm <- as.numeric(m)
mat <- matrix(0, nrow = g * ncol(m), ncol = n)
mat[ cbind(1:nrow(mat), mm)] <- 1

mat
#       [,1] [,2] [,3]
#[1,]    1    0    0
#[2,]    0    1    0

#[3,]    1    0    0
#[4,]    0    0    1

#[5,]    0    1    0
#[6,]    0    0    1

# mat is half the answer :)
# the other half is
mat[nrow(mat):1, ]

#      [,1] [,2] [,3]
#[1,]    0    0    1
#[2,]    0    1    0

#[3,]    0    0    1
#[4,]    1    0    0

#[5,]    0    1    0
#[6,]    1    0    0

soln <- rbind(mat, mat[nrow(mat):1, ])

# as suggested by the OP to split the soln 
d <- split(data.frame(soln), rep(1:(nrow(soln)/g), each=g))

答案 1 :(得分:1)

精明的读者会注意到这个问题可以简化为:&#34;如何生成 2的幂的所有成对排列?&# 34; 通过这种方式查看,我们可以避免最初处理二进制向量并将其保存到最后一步。

使用基本R函数intToBitsthis answer到问题How to convert integer numbers into binary vector?,以及任何可以生成特定长度的排列的函数(有很多软件包:{{1 }},gtools::permutationsRcppAlgos::permuteGeneraliterpc),我们可以在一行中获得所需的结果。

arrangements::permutations

概括很容易。

library(gtools)
t(sapply(t(gtools::permutations(3, 2, 2^(0:2))),  
         function(x) {as.integer(intToBits(x))})[1:3, ])

      [,1] [,2] [,3]
 [1,]    1    0    0
 [2,]    0    1    0

 [3,]    1    0    0
 [4,]    0    0    1

 [5,]    0    1    0
 [6,]    1    0    0

 [7,]    0    1    0
 [8,]    0    0    1

 [9,]    0    0    1
[10,]    1    0    0

[11,]    0    0    1
[12,]    0    1    0


更新

我只是张贴这个来指出@Suren的回答是如何正确的。

  

OP正在寻找排列而不是组合

从评论中的对话中,您会看到@Suren的解决方案在群组数量增加时没有给出正确的结果(&#34;我也试图获得三个分组的代替2(或任何数字)&#34; &#34;这是切断一些解决方案&#34; )。

@ Suren的回答似乎与bitPairwise <- function(numBits, groupSize) { t(sapply(t(gtools::permutations(numBits, groupSize, 2^(0:(numBits-1)))), function(x) {as.integer(intToBits(x))})[1:numBits, ]) } bitPairwise(numBits = 6, groupSize = 3)[1:12, ] [,1] [,2] [,3] [,4] [,5] [,6] [1,] 1 0 0 0 0 0 [2,] 0 1 0 0 0 0 [3,] 0 0 1 0 0 0 [4,] 1 0 0 0 0 0 [5,] 0 1 0 0 0 0 [6,] 0 0 0 1 0 0 [7,] 1 0 0 0 0 0 [8,] 0 1 0 0 0 0 [9,] 0 0 0 0 1 0 [10,] 1 0 0 0 0 0 [11,] 0 1 0 0 0 0 [12,] 0 0 0 0 0 1 给出了正确的结果。之所以这样,是因为g = 2的排列等于1:n choose 21:n choose 2组合的组合(注意n:1 choose 2被颠倒)。这正是@ Suren的答案正在做的事情(即生成组合选择2,以相反的顺序写入它们并组合)。

1:n

使用OP中的给定示例,它以不同的顺序给出相同的结果:

## original version
surenFun <- function(n, g) {
    m <- combn(n, g)
    mm <- as.numeric(m)
    mat <- matrix(0, nrow = g * ncol(m), ncol = n)
    mat[ cbind(1:nrow(mat), mm)] <- 1
    soln <- rbind(mat, mat[nrow(mat):1, ])
    split(data.frame(soln), rep(1:(nrow(soln)/g), each=g))
}

## Here is the corrected version
surenFunCorrected <- function(n, g) {
    ## changed combn to gtools::permutations or any other
    ## similar function that can generate permutations
    m <- gtools::permutations(n, g)
    ## you must transpose m
    mm <- as.numeric(t(m))
    ## change ncol(m) to nrow(m)
    mat <- matrix(0, nrow = g * nrow(m), ncol = n)
    mat[ cbind(1:nrow(mat), mm)] <- 1
    ## removed soln
    split(data.frame(mat), rep(1:(nrow(mat)/g), each=g))
}

让我们使用## The order is slightly different match(surenFunCorrected(3, 2), surenFun(3, 2)) [1] 1 2 6 3 5 4 all(surenFunCorrected(3, 2) %in% surenFun(3, 2)) [1] TRUE all(surenFun(3, 2) %in% surenFunCorrected(3, 2)) [1] TRUE g = 3进行测试。

n = 4