首页 文章

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

提问于
浏览
3

我正在寻找一种智能方法来生成长度为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 回答

  • 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

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

    使用基本R函数 intToBitsthis answer到问题How to convert integer numbers into binary vector?,以及任何可以生成特定长度排列的函数(有很多软件包: gtools::permutationsRcppAlgos::permuteGeneraliterpcarrangements::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
    

    推广很容易 .

    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
    

    更新

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

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

    从评论中的对话中,您会看到@Suren的解决方案在组数增加时没有给出正确的结果("I am also trying to get groupings of three instead of 2 (or any number)"和"This is cutting off some solutions") .

    似乎@ Suren的回答用 g = 2 给出了正确的结果 . 这是如此,因为 1:n choose 2 的排列等于 1:n choose 2 的组合与 n:1 choose 2 的组合(注意 1:n 被颠倒) . 这正是@ Suren的答案正在做的事情(即生成组合选择2,以相反的顺序编写它们并组合) .

    ## 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))
    }
    

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

    ## 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 = 3n = 4 测试一下 .

    ## N.B. all of the original output is
    ## contained in the corrected output
    all(surenFun(4, 3) %in% surenFunCorrected(4, 3))
    [1] TRUE
    
    ## However, there are 16 results
    ## not returned in the original
    leftOut <- which(!(surenFunCorrected(4, 3) %in% surenFun(4, 3)))
    leftOut
    [1]  3  5  6  7  8  9 11 12 13 14 16 17 18 19 20 22
    
    ## E.g. 3 examples that were left out
    surenFunCorrected(4, 3)[leftOut[c(1,8,16)]]
    $`3`
      X1 X2 X3 X4
    7  1  0  0  0
    8  0  0  1  0
    9  0  1  0  0
    
    $`12`
       X1 X2 X3 X4
    34  0  1  0  0
    35  0  0  0  1
    36  0  0  1  0
    
    $`22`
       X1 X2 X3 X4
    64  0  0  0  1
    65  0  1  0  0
    66  0  0  1  0
    

相关问题