20

如果我想使用二进制搜索选择 data.table 中不包含键变量中特定值的所有行,会发生什么情况?顺便说一句,我想做的正确术语是什么?是“不加入”吗?是“负选择”吗?

DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)
setkey(DT,x)

让我们对 x=="a" 但使用二分搜索的所有行进行正选择

DT["a"]

这很漂亮,但我想要相反的。我想要所有不是“a”的行,换句话说,x!=“a”

DT[x!="a"]

那是矢量扫描。上述行有效,但使用矢量扫描。我想使用二进制。我期待以下工作,但唉......

DT[!"a"]
DT[-"a"]

以上两个都不起作用,尝试使用 nomatch 让我无处可去。

4

2 回答 2

19

成语是这样的:

DT[-DT["a", which=TRUE]]

   x y v
1: b 1 4
2: b 3 5
3: b 6 6
4: c 1 7
5: c 3 8
6: c 6 9

灵感来自:


更新。v1.8.3 中的新功能是非连接语法。Farrel 的第一个期望(!而不是-)已经实现:

DT[-DT["a",which=TRUE,nomatch=0],...]   # old idiom
DT[!"a",...]                            # same result, now preferred.

有关更多详细信息和示例,请参阅新闻项目。

于 2012-09-07T14:08:57.063 回答
3

安德烈的回答很棒,而且我可能会使用。不过,有趣的是,以下构造似乎(只是有点)更快,尤其是随着 data.tables 大小的增加。

DT[J(x = unique(DT)[x!="a"][,x])]

##-------------------------------- Timings -----------------------------------##

library(data.table)
library(rbenchmark)

DT = data.table(x=rep(c("a","b","c"),each=45e5), y=c(1,3,6), v=1:9, key="x")
Josh <- function() DT[J(x = unique(DT)[x!="a"][,x])]
Andrie <- function() DT[-DT["a", which=TRUE]]

## Compare results
identical(Josh(), setkey(Andrie(), "x"))  
# [1] TRUE

## Compare timings
benchmark(replications = 10, order="relative", Josh=Josh(), Andrie=Andrie())
    test replications elapsed relative user.self sys.self user.child sys.child
1   Josh           10   17.50    1.000     14.78      3.6         NA        NA
2 Andrie           10   18.75    1.071     16.52      3.2         NA        NA

DT[,x]如果可以返回data.table而不是向量,我会特别想使用它。然后,可以将构造简化为DT[unique(DT[,x])[x!="a"]]. 此外,即使键中有多个列,它也可以工作,而它目前没有。

于 2012-09-07T17:30:15.563 回答