考虑我有一个这样的数据框,
set.seed(1)
q<-100
df <- data.frame(Var1 = round(runif(q,1,50)),
Var2 = round(runif(q,1,50)),
Var3 = round(runif(q,1,50)),
Var4 = round(runif(q,1,50)))
attach(df)
如您所知,
q
代表设置数据帧中每列的长度。我想对列的所有可能组合进行过滤。可以是任何东西。假设我正在寻找前两列之和与后两列之和的总和是否大于1。
使用
expand.grid()
函数可以实现这一目标。a <- Sys.time()
expanded <- expand.grid(Var1, Var2, Var3, Var4)
Sys.time() - a
Time difference of 8.31997 secs
expanded <- expanded[rowSums(expanded[,1:2])/ rowSums(expanded[,3:4])>1,]
但是,这需要很多时间!为了使速度更快,我尝试在this问题中使用
rep.int()
函数来回答问题,并设计了自己的函数。myexpand <- function(...) {
sapply(list(...),function(y) rep.int(y, prod(lengths(list(...)))/length(y)))
}
但这不是那么有希望。与我的期望和
expand.grid
相比,它需要花费更多时间。而且,如果我设置更大的q
,它将成为一个麻烦事!在应用
expand.grid
或myexpand
之前,是否可以通过矩阵操作更快地(1-2秒)实现这一目标?而且,我想知道使用R之类的解释语言是否有缺点。软件建议也可以接受。 最佳答案
对于这种特殊条件(即总和的比率> 1),您可能需要考虑使用data.table
包:
system.time({
#generate permutations of Var1 & Var2 and Var3 & Var4
DT12 <- DT[, CJ(Var1=Var1, Var2=Var2, unique=TRUE)][, s12 := Var1 + Var2]
DT34 <- DT[, CJ(Var3=Var3, Var4=Var4, unique=TRUE)][, s34 := Var3 + Var4]
#perform a non-equi join
DT12[DT34, on=.(s12>s34), allow.cartesian=TRUE,
.(Var1=x.Var1, Var2=x.Var2, Var3=i.Var3, Var4=i.Var4)][, s12:=NULL]
})
定时:
user system elapsed
0.02 0.06 0.08
输出:
Var1 Var2 Var3 Var4
1: 2 5 2 4
2: 4 3 2 4
3: 5 2 2 4
4: 2 6 2 4
5: 4 4 2 4
---
1753416: 50 49 49 48
1753417: 50 50 49 48
1753418: 50 49 49 49
1753419: 50 50 49 49
1753420: 50 50 49 50
数据:
library(data.table)
set.seed(1)
q <- 100
DT <- data.table(Var1 = round(runif(q,1,50)),
Var2 = round(runif(q,1,50)),
Var3 = round(runif(q,1,50)),
Var4 = round(runif(q,1,50)))
编辑:对于正数的总和,您可以使用以下命令(注意:这不会比使用Rcpp方法快)。
system.time({
S <- DT[, .(UB=90 - Var1, C1=Var1)]
for (k in 2:4) {
S <- DT[S, on=paste0("Var", k, "<UB"), allow.cartesian=TRUE,
mget(c(names(S), paste0("x.Var", k)))]
setnames(S, paste0("x.Var", k), paste0("C", k))
S[, UB := UB - get(paste0("C",k))]
}
S[, UB := NULL][rowSums(S)>30L]
})
定时:
user system elapsed
3.48 4.06 3.51
输出,
S
:> S
C1 C2 C3 C4
1: 14 33 14 6
2: 14 33 14 25
3: 14 33 14 24
4: 14 33 14 19
5: 14 33 14 10
---
34914725: 31 39 3 8
34914726: 31 39 3 8
34914727: 31 39 3 9
34914728: 31 39 3 16
34914729: 31 39 3 8
关于r - 为所有可能的组合实现过滤的更快方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57457590/