我有一个包含1000多个二进制列的data.table,但是一个简单的例子是:
dt <- data.table(one=c(1,1,0), two=c(0,0,1), three=c(1,1,0), four=c(1,1,1))
我想计算预定义列数的每种组合都等于1的次数。因此,例如,如果我想计算每两列之间的“ 1”匹配项,我可以这样做:
a <- combn(names(dt),2)[1,]
b <- combn(names(dt),2)[2,]
for(i in 1:length(a)){
print(c(a[i], b[i], dt[get(a[i])==1 & get(b[i])==1,.N]))
}
我想改变合并的列数,我需要一种有效的方法来实现这一点。
我可以像这样用eval(parse())
解决这个问题:
n <- 3 # number of columns to combine
for(i in 1:n){assign(paste0("a", i), combn(names(dt),n)[i,])}
for(i in 1:length(a1)){
expr1 <- paste0("c(",paste0(rep("a", n), 1:n, "[i]", collapse=","), ")")
expr2 <- paste0("dt[",paste0("get(",rep("a", n), 1:n, ")", sep=" ==TRUE ", collapse = " & "),",.N]")
print(c(eval(parse(text=expr1)), eval(parse(text=expr2))))
}
尽管如此,对上面的简单代码进行的微基准测试表明,get()
比eval(parse())
快5倍。
有效的方法是什么?
答案 0 :(得分:1)
这是个主意,
sapply(combn(dt, 3, simplify = FALSE), function(i){
v1 <- sum(rowSums(i) == ncol(i));
setNames(v1, paste(names(i), collapse = '-'))
})
# one-two-three one-two-four one-three-four two-three-four
# 0 0 2 0
答案 1 :(得分:1)
将指示的all1
用作combn
中的函数:
k <- 3
DF <- as.data.frame(dt)
all1 <- combn(names(DF), k, function(x) sum(apply(DF[, x] == 1, 1, all)))
data.frame(t(combn(names(DF), k)), all1)
给予:
X1 X2 X3 all1
1 one two three 0
2 one two four 0
3 one three four 2
4 two three four 0