在R中的data.table中选择NA
如何选择数据表中主键中缺少值的所有行在R中的data.table中选择NA,r,select,data.table,missing-data,na,R,Select,Data.table,Missing Data,Na,如何选择数据表中主键中缺少值的所有行 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.nax,]几乎与例如DT[a,]一样快,因此在实践中,这可能并不重要: li
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.nax,]几乎与例如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
随着返回子集的大小减小(例如添加更多组),差异变得明显。在一列上进行矢量扫描并不太糟糕,但在两列或更多列上它会很快退化
也许NAs应该可以加入。不过,我似乎还记得有一个问题。这里有一些历史链接。它提到NA_integer_uu在内部是一个负整数。这会使基数/计数排序iirc上移,导致setkey变慢。但是它在重新访问的列表上。这现在在v1.8.11中实现。发件人:
o二进制搜索现在能够对NA/NAN进行子集划分,还可以通过匹配NAs/NAN执行连接和合并
尽管您必须提供正确的NA_real_uu、NA_character_u等。。目前明确地说
关于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 # <~~~
@Matthew-使用which=TRUE来隔离搜索时间是个好主意。而且,DT[is.nax]似乎仍然比我能想到的任何东西都要好。我最初尝试了DT[-DT[na.ommituniquedt[,1,with=FALSE],which=TRUE],],但它的速度很慢,就像你可能猜到的那样。这不是上面提到的问题,但unique真的是提取一个键控列或一组键控列的唯一级别的最快方法吗?嗨,Josh。我迅速地看了一眼。似乎[,1,with=FALSE]保留了键ok,所以unique.data.table应该调用duplist,它的工作原理与whichdiff类似=0,但在列列表上。所以是的,唯一的部分应该和向量扫描一样快,因为它知道它被排序了。但由于除了一个团体外,其他所有团体都加入了,这可能会给我带来一条已知的皱纹。在那里搜索mapply和注释。我想在这种情况下,这是一种痛苦。希望尽快用bit::vecseq替换!此外,还可以从尚未实现的列引用中获益。目前,DT[,j,with=FALSE]将j列的一个副本复制到新表中。浅层复制可能是即时的,但它需要标记它们,因此,如果:=稍后使用,则可以在列级别进行更改复制。Josh,我终于消除了对mapply的可怕内部调用。最后,bit::vecseq是在R中实现的,所以我在C中实现了它,并在内部使用它。几分钟的减速现在应该是几秒钟。mult=first的解决方法不再需要。在R-Forge上的v1.8.3中。嗯,我希望如此。至少在我的测试中,+1很棒!在最后一行中,DT[NA]现在似乎进行了连接?@MattDowle,似乎没有rbenchmark出于某种原因将其从NA_character_更改为NA以显示。不错,但你无法从CRAN获得1.8.11,你需要R-Forge,他们的二进制结构目前已被破坏:CRAN只提供1.8.10nice+1。你怎么过滤不到NA。例如:DT[J!NA_real_]不起作用。@AndreSilva,试试DT[!JNA_real_]。