如何在data.table中进行否定/无匹配/反向搜索?

时间:2012-09-07 13:28:48

标签: r select data.table

如果我想选择data.table中使用二进制搜索在键变量中不包含特定值的所有行,会发生什么?顺便问一下,我想做什么的正确行话是什么?它是“nojoin”吗?这是“否定选择”吗?

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无处可玩。

2 个答案:

答案 0 :(得分: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.

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

答案 1 :(得分:3)

Andrie的答案很棒,而且我可能会使用它。有趣的是,以下构造似乎(只是稍微)更快,特别是当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"]]。此外,即使密钥中有多个列,它也可以工作,但目前它没有。