在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_]。