如何选择数据表中主键中缺少值的所有行。
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
如何选择数据表中主键中缺少值的所有行。
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
幸运的是,DT[is.na(x),]
几乎和 (eg) 一样快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
随着返回的子集的大小减小(例如添加更多组),差异变得明显。单列上的矢量扫描还不错,但在 2 列或更多列上它会迅速降级。
也许 NA 应该可以加入。不过,我似乎记得有一个问题。这是从 FR#1043 链接的一些历史记录Allow or disallow NA in keys?. 它在那里提到NA_integer_
内部是一个负整数。这会使基数/计数排序(iirc)出错,从而导致setkey
速度变慢。但它在重新访问的列表中。
o 二分搜索现在能够对
NA
/NaN
s 进行子集化,并且还可以通过匹配s/ s 来执行joins
和执行。merges
NA
NaN
尽管此时您必须明确提供正确的NA
(NA_real_
等NA_character_
)。
关于OP的数据:
DT[J(NA_character_)] # or for characters simply DT[NA_character_]
# x y v
# 1: NA 1 7
# 2: NA 3 8
# 3: NA 6 9
此外,这是来自@JoshOBrien 帖子的相同基准,添加了对 NA 的二进制搜索:
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),],
DT[NA_character_],
replications=20)
test replications elapsed relative user.self sys.self
1 DT["a", ] 20 4.763 1.238 4.000 0.567
2 DT[is.na(x), ] 20 5.399 1.403 4.537 0.794
3 DT[NA] 20 3.847 1.000 3.215 0.600 # <~~~