创建二进制向量的组合

Mat*_*lli 5 binary combinations r

我想创建一个由固定数字0和1组成的二进制向量的所有可能组合.例如:dim(v)= 5x1; N1 = 3; N0 = 2; 在这种情况下,我希望有类似的东西:

  1,1,1,0,0
  1,1,0,1,0
  1,1,0,0,1
  1,0,1,1,0
  1,0,1,0,1
  1,0,0,1,1
  0,1,1,1,0
  0,1,1,0,1
  0,1,0,1,1
  0,0,1,1,1
Run Code Online (Sandbox Code Playgroud)

我找到了一些帮助阅读这篇文章 创建所有可能的0,1或2"1"的长度为n的二进制向量 的组合,但我想只生成我需要的组合,避免任何浪费空间(我认为问题会随着n)而呈指数增长

Mar*_*pov 6

您可以尝试这种方法:

f <- function(n=5,m=3)
 t(apply(combn(1:n,m=m),2,function(cm) replace(rep(0,n),cm,1)))

f(5,3)
#       [,1] [,2] [,3] [,4] [,5]
#  [1,]    1    1    1    0    0
#  [2,]    1    1    0    1    0
#  [3,]    1    1    0    0    1
#  [4,]    1    0    1    1    0
#  [5,]    1    0    1    0    1
#  [6,]    1    0    0    1    1
#  [7,]    0    1    1    1    0
#  [8,]    0    1    1    0    1
#  [9,]    0    1    0    1    1
# [10,]    0    0    1    1    1
Run Code Online (Sandbox Code Playgroud)

这个想法是生成 1 的所有索引组合,然后使用它们产生最终结果。

相同方法的另一种风格:

f.2 <- function(n=5,m=3)
  t(combn(1:n,m,FUN=function(cm) replace(rep(0,n),cm,1)))
Run Code Online (Sandbox Code Playgroud)

第二种方法大约快两倍:

library(rbenchmark)
benchmark(f(16,8),f.2(16,8))
#         test replications elapsed relative user.self sys.self user.child sys.child
# 2 f.2(16, 8)          100   5.706    1.000     5.688    0.017          0         0
# 1   f(16, 8)          100  10.802    1.893    10.715    0.082          0         0
Run Code Online (Sandbox Code Playgroud)

基准

f.akrun <- function(n=5,m=3) {

  indx <- combnPrim(1:n,m)

  DT <- setDT(as.data.frame(matrix(0, ncol(indx),n)))
  for(i in seq_len(nrow(DT))){
    set(DT, i=i, j=indx[,i],value=1) 
  }
  DT  
}

benchmark(f(16,8),f.2(16,8),f.akrun(16,8))
#            test replications elapsed relative user.self sys.self user.child sys.child
# 2     f.2(16, 8)          100   5.464    1.097     5.435    0.028          0         0
# 3 f.akrun(16, 8)          100   4.979    1.000     4.938    0.037          0         0
# 1       f(16, 8)          100  10.854    2.180    10.689    0.129          0         0
Run Code Online (Sandbox Code Playgroud)

@akrun 的解决方案 ( f.akrun) 比 快约 10% f.2

[编辑] 另一种方法,更快更简单:

f.3 <- function(n=5,m=3) t(combn(n,m,tabulate,nbins=n))
Run Code Online (Sandbox Code Playgroud)


Rol*_*and 6

Marat答案的稍快版本:

f.roland <- function(n, m) {
  ind <- combn(seq_len(n), m)
  ind <- t(ind) + (seq_len(ncol(ind)) - 1) * n
  res <- rep(0, nrow(ind) * n)
  res[ind] <- 1
  matrix(res, ncol = n, nrow = nrow(ind), byrow = TRUE)
}

all.equal(f.2(16, 8), f.roland(16, 8))
#[1] TRUE
library(rbenchmark)
benchmark(f(16,8),f.2(16,8),f.roland(16,8))

#             test replications elapsed relative user.self sys.self user.child sys.child
#2      f.2(16, 8)          100   5.693    1.931     5.670    0.020          0         0
#3 f.roland(16, 8)          100   2.948    1.000     2.929    0.017          0         0
#1        f(16, 8)          100   8.287    2.811     8.214    0.066          0         0
Run Code Online (Sandbox Code Playgroud)