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 请求)一次取 m
(simplify=FALSE
确保结果具有列表结构)。 lapply
调用一个隐式循环来迭代 m
从 1 到 3 和 returns 列表的列表。 do.call(c,...)
将列表的列表转换为普通列表。
您可以使用 col.i
从 dat
中获取某些列,例如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
假设我们有以下数据集
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 请求)一次取 m
(simplify=FALSE
确保结果具有列表结构)。 lapply
调用一个隐式循环来迭代 m
从 1 到 3 和 returns 列表的列表。 do.call(c,...)
将列表的列表转换为普通列表。
您可以使用 col.i
从 dat
中获取某些列,例如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