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"]

上記の2つは機能せず、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 の新機能は、not-join 構文です。ファレルの最初の期待 (!ではなく-) が実装されました:

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

より詳細な情報と例については、 NEWS項目を参照してください。

于 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

ベクトルではなくdata.tableDT[,x]を返すようにできれば、特にこれを使用したくなるでしょう。次に、構造を少し単純化して. また、キーに複数の列がある場合でも機能しますが、現在は機能していません。DT[unique(DT[,x])[x!="a"]]

于 2012-09-07T17:30:15.563 に答える