データ テーブルの主キーに欠損値があるすべての行を選択するにはどうすればよいですか。
DT = data.table(x=rep(c("a","b",NA),each=3), y=c(1,3,6), v=1:9)
setkey(DT,x)
特定の値を選択するのは簡単です
DT["a",]
欠損値を選択するにはベクトル検索が必要なようです。バイナリ検索は使用できません。私の考えは正しいでしょうか?
DT[NA,]# does not work
DT[is.na(x),] #does work
ベストアンサー1
幸いなことに、DT[is.na(x),]
は (例) とほぼ同じくらい高速なのでDT["a",]
、実際には、これはあまり問題にならないかもしれません。
library(data.table)
library(rbenchmark)
DT = data.table(x=rep(c("a","b",NA),each=3e6), y=c(1,3,6), v=1:9)
setkey(DT,x)
benchmark(DT["a",],
DT[is.na(x),],
replications=20)
# test replications elapsed relative user.self sys.self user.child
# 1 DT["a", ] 20 9.18 1.000 7.31 1.83 NA
# 2 DT[is.na(x), ] 20 10.55 1.149 8.69 1.85 NA
===
マシューからの追加(コメントに収まりきらない):
ただし、上記のデータには非常に大きなグループが 3 つあります。したがって、バイナリ検索の速度の利点は、ここでは大きなサブセットを作成する時間 (データの 1/3 がコピーされる) によって左右されます。
benchmark(DT["a",], # repeat select of large subset on my netbook
DT[is.na(x),],
replications=3)
test replications elapsed relative user.self sys.self
DT["a", ] 3 2.406 1.000 2.357 0.044
DT[is.na(x), ] 3 3.876 1.611 3.812 0.056
benchmark(DT["a",which=TRUE], # isolate search time
DT[is.na(x),which=TRUE],
replications=3)
test replications elapsed relative user.self sys.self
DT["a", which = TRUE] 3 0.492 1.000 0.492 0.000
DT[is.na(x), which = TRUE] 3 2.941 5.978 2.932 0.004
返されるサブセットのサイズが小さくなると (たとえば、グループを追加すると)、違いが明らかになります。 1 つの列でのベクトル スキャンはそれほど悪くありませんが、2 つ以上の列ではすぐに低下します。
NA も参加できるといいかもしれません。でも、その点については覚えているような気がします。ここにリンクされている履歴があります。FR#1043 キーに NA を許可するか禁止するか?NA_integer_
内部的には負の整数であると書かれています。これにより基数/カウント ソートが失敗し (記憶が確かなら)、結果的にsetkey
処理速度が低下します。ただし、再検討すべきリストに載っています。