生成具有N / 2个零/ 1的{0,1} ^ N的所有子集

时间:2015-11-26 19:34:01

标签: r

我正在尝试用R生成所有长度为N的序列(假设N是偶数),这样零的数量正好是N / 2.

3 个答案:

答案 0 :(得分:2)

我认为这是你正在寻找的东西。我使用expand.grid生成了所有可能的二进制组合,并选择了其中包含N/2个二进制组合的组合。

bin.combs <- function(N){
  cbs <- as.matrix(expand.grid(rep(list(0:1),N)))
  cbs <- cbs[rowSums(cbs)==N/2,]
  unname(cbs)
}

# > bin.combs(4)
#      [,1] [,2] [,3] [,4]
# [1,]    1    1    0    0
# [2,]    1    0    1    0
# [3,]    0    1    1    0
# [4,]    1    0    0    1
# [5,]    0    1    0    1
# [6,]    0    0    1    1

修改

# @Matthew Lundberg
bin.combs3 <- function(N){
  apply(combn(N,N/2), 2, FUN=function(x) 1:N %in% x)
}

# @Bernardo
bin.combs2 <- function(N){
  vec <- rep(c(0,1),N/2)
  cbs <- permn(vec)
  cbs[!duplicated(cbs)]
}

这是迄今为止提出的解决方案的基准。结果表明我和@Matthews解决方案非常接近。

microbenchmark(bin.combs(8), bin.combs2(8), bin.combs3(8), times=20)
# Unit: microseconds
#             expr        min         lq        mean      median          uq        max neval
#     bin.combs(8)    551.916    586.021    788.5850    663.6950    736.8880   3200.565    20
#    bin.combs2(8) 483857.505 522567.683 546706.0648 545832.1185 561677.2175 672247.779    20
#    bin.combs3(8)    688.192    749.524    809.2446    795.3495    874.2095   1003.857    20

答案 1 :(得分:2)

combn获得组合。然后,您可以从1:N中选择这些条目。下面矩阵中的列是解决方案。

> f <- function(N) apply(combn(N,N/2), 2, FUN=function(x) 1:N %in% x)
> f(4)
      [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
[1,]  TRUE  TRUE  TRUE FALSE FALSE FALSE
[2,]  TRUE FALSE FALSE  TRUE  TRUE FALSE
[3,] FALSE  TRUE FALSE  TRUE FALSE  TRUE
[4,] FALSE FALSE  TRUE FALSE  TRUE  TRUE

答案 2 :(得分:1)

SimonG的方法的另一种方法是首先定义一个包含所需零和一个数的向量,然后使用包combinat获取所有排列。应该更有效,特别是对于大N,因为你不必生成所有可能性然后将其子集化。

library(combinat)
N = 4
vec = rep(c(0,1),N/2)
permn(vec)