R:从所有可能的组合中选择特定数量的组合

R: Choosing specific number of combinations from all possible combinations

假设我们有以下数据集

set.seed(144) 
dat <- matrix(rnorm(100), ncol=5)

以下函数创建所有可能的列组合并删除第一个

(cols <- do.call(expand.grid, rep(list(c(F, T)), ncol(dat)))[-1,])
#     Var1  Var2  Var3  Var4  Var5
# 2   TRUE FALSE FALSE FALSE FALSE
# 3  FALSE  TRUE FALSE FALSE FALSE
# 4   TRUE  TRUE FALSE FALSE FALSE
# ...
# 31 FALSE  TRUE  TRUE  TRUE  TRUE
# 32  TRUE  TRUE  TRUE  TRUE  TRUE

我的问题是如何只计算单一、二元和三元组合?

使用以下函数选择包含不超过 3 个 TRUE 值的行适用于此向量:cols[rowSums(cols)<4L, ] 但是,对于较大的向量,它会给出以下错误,主要是因为 expand.grid 中的错误与长向量:

Error in rep.int(seq_len(nx), rep.int(rep.fac, nx)) : 
  invalid 'times' value
In addition: Warning message:
In rep.fac * nx : NAs produced by integer overflow

有什么建议可以让我只计算单个、二进制和三重组合吗?

你可以试试

cols[rowSums(cols) < 4L, ]

或者

cols[Reduce(`+`, cols) < 4L, ]

您可以使用此解决方案:

col.i <- do.call(c,lapply(1:3,combn,x=5,simplify=F))
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2
# 
# <...skipped...>
# 
# [[24]]
# [1] 2 4 5
# 
# [[25]]
# [1] 3 4 5

这里,col.i是一个列表,每个元素都包含列索引。

工作原理:combn 生成从 1 到 5 的所有数字组合(由 x=5 请求)一次取 msimplify=FALSE确保结果具有列表结构)。 lapply 调用一个隐式循环来迭代 m 从 1 到 3 和 returns 列表的列表。 do.call(c,...) 将列表的列表转换为普通列表。

您可以使用 col.idat 中获取某些列,例如dat[,col.i[[1]],drop=F](1 是列组合的索引,因此您可以使用 1 到 25 之间的任何数字;drop=F 确保当您仅从 dat 中选择一列时,结果是未简化为向量,这可能会导致意外的程序行为)。另一种选择是使用 lapply,例如

lapply(col.i, function(cols) dat[,cols])

这将 return 一个数据框列表,每个数据框包含 dat.

的特定列子集

如果您想将列索引作为布尔矩阵获取,您可以使用:

col.b <- t(sapply(col.i,function(z) 1:5 %in% z))
#       [,1]  [,2]  [,3]  [,4]  [,5]
# [1,]  TRUE FALSE FALSE FALSE FALSE
# [2,] FALSE  TRUE FALSE FALSE FALSE
# [3,] FALSE FALSE  TRUE FALSE FALSE
# ...

[更新]

更高效的实现:

library("gRbase")

coli <- function(x=5,m=3) {
    col.i <- do.call(c,lapply(1:m,combnPrim,x=x,simplify=F))

    z <- lapply(seq_along(col.i), function(i) x*(i-1)+col.i[[i]])
    v.b <- rep(F,x*length(col.i))
    v.b[unlist(z)] <- TRUE
    matrix(v.b,ncol=x,byrow = TRUE)
}

coli(70,5) # takes about 30 sec on my desktop