【发布时间】:2017-12-10 19:07:05
【问题描述】:
我是data.table 的新手,似乎遗漏了一些明显的东西。我有一张桌子:
DT = data.table(A = c("x","y","y","z"), B = c("y","x","x","z"), value = 1:4)
setkey(DT, A, B)
现在我想找到A 或B 为"y" 的所有行(使用二进制搜索,我的实际表更大,操作必须执行数百万次)。我无法在一个语句中弄清楚如何做到这一点,因为,
DT[.("y", "y"), nomatch=0]
只给我(A & B) == "y" 的行(但我想要(A | B) == "y")。我现在做的是:
uA <- unique(DT[, A])
rbind(DT[.(uA, "y"), nomatch=0], DT[.("y"), nomatch=0])
但我觉得一定有更直观的方法。
感谢您的帮助!
基准测试
包括改编自@Frank's comment on Binary search DT with key on two columns using alternative (OR) instead of a conjunction的代码
n = 1e6
DT = data.table(A = sample(letters, n, replace = TRUE),
B = sample(letters, n, replace = TRUE), value = 1:n)
setkey(DT, A, B)
uA <- unique(DT[, A])
library(microbenchmark)
Union = function(){
mya = DT[A=="y", which=TRUE]
myb = DT[B=="y", which=TRUE]
DT[union(mya,myb)]
}
microbenchmark(
"reduce" = DT[DT[, Reduce('|', lapply(.SD, '==', 'y')), .SDcols = A:B]],
"rbind" = rbind(DT[.(uA, "y"), nomatch=0], DT[.("y"), nomatch=0]),
"union" = Union()
)
Unit: milliseconds
expr min lq mean median uq max neval
reduce 9.922728 10.116613 11.422823 10.226871 11.803204 25.453557 100
rbind 2.596139 2.734751 2.916620 2.850199 3.113995 3.453326 100
union 5.393815 5.725917 6.221544 5.906222 6.758622 14.019206 100
【问题讨论】:
-
您可以使用
DT[DT[, Reduce('|', lapply(.SD, '==', 'y')), .SDcols = A:B]] -
非常感谢,这行得通! (而且它的速度是我的解决方案的两倍)。虽然没有更直观的方法可以做到这一点,但我感到很惊讶。
-
感谢@Henrik,在我的研究中错过了那个
-
@Henrik 您可以发布该代码作为答案吗?我无法让该解决方案产生等效的输出。
-
@Hendrik 查看我的编辑。我让它工作了,但它似乎也慢了。
标签: r data.table