R 有效计算data.table中的非NA元素

R 有效计算data.table中的非NA元素,r,data.table,R,Data.table,有时我需要在我的数据表的一列或另一列中计算非NA元素的数量。最好的数据表定制方法是什么 为了具体化,让我们使用以下方法: DT <- data.table(id = sample(100, size = 1e6, replace = TRUE), var = sample(c(1, 0, NA), size = 1e6, replace = TRUE), key = "id") 但这有一个不幸的缺点,N没有被分配到缺少var的任何行,即DT[is.na(

有时我需要在我的
数据表的一列或另一列中计算非
NA
元素的数量。最好的
数据表
定制方法是什么

为了具体化,让我们使用以下方法:

DT <- data.table(id = sample(100, size = 1e6, replace = TRUE),
                 var = sample(c(1, 0, NA), size = 1e6, replace = TRUE), key = "id")
但这有一个不幸的缺点,
N
没有被分配到缺少
var
的任何行,即
DT[is.na(var),N]=na

因此,我通过附加以下内容来解决此问题:

DT[!is.na(var), N:= .N, by = id][ , N := max(N, na.rm = TRUE), by = id] #OPTION 1
然而,我不确定这是最好的方法;对于
data.frame
s,我想到的另一个选项和模拟问题建议的一个选项是:

DT[ , N := length(var[!is.na(var)]), by = id] # OPTION 2

比较这些试验的计算时间(平均超过100次试验),最后一次似乎是最快的:

OPTION 1 | OPTION 2 | OPTION 3
  .075   |   .065   |   .043

是否有人知道一种更快捷的方法来处理
数据。表

是的,第三个选项似乎是最好的。我已经添加了另一个,只有当您考虑将DATA表的键从“代码> ID <代码>更改为<代码> var >代码>时,该选项才有效,但选项3仍然是您的数据中最快的。
library(microbenchmark)
library(data.table)

dt<-data.table(id=(1:100)[sample(10,size=1e6,replace=T)],var=c(1,0,NA)[sample(3,size=1e6,replace=T)],key=c("var"))

dt1 <- copy(dt)
dt2 <- copy(dt)
dt3 <- copy(dt)
dt4 <- copy(dt)

microbenchmark(times=10L,
               dt1[!is.na(var),.N,by=id][,max(N,na.rm=T),by=id],
               dt2[,length(var[!is.na(var)]),by=id],
               dt3[,sum(!is.na(var)),by=id],
               dt4[.(c(1,0)),.N,id,nomatch=0L])
# Unit: milliseconds
#                                                         expr      min       lq      mean    median        uq       max neval
#  dt1[!is.na(var), .N, by = id][, max(N, na.rm = T), by = id] 95.14981 95.79291 105.18515 100.16742 112.02088 131.87403    10
#                     dt2[, length(var[!is.na(var)]), by = id] 83.17203 85.91365  88.54663  86.93693  89.56223 100.57788    10
#                             dt3[, sum(!is.na(var)), by = id] 45.99405 47.81774  50.65637  49.60966  51.77160  61.92701    10
#                        dt4[.(c(1, 0)), .N, id, nomatch = 0L] 78.50544 80.95087  89.09415  89.47084  96.22914 100.55434    10

库(微基准)
库(数据表)

dt@MichaelChirico,请查看(如果您发现有不清楚/需要添加的内容,请告诉我们)。还有另一个选项:
dt5[,.N[!is.na(var)],by=id]
-在我的系统中是第三快的,比选项1和2好得多。出于某种原因,选项3生成二进制响应(0,1)如果使用了多个“by”变量,则不使用计数。建议的选项5给出了正确的计数。
OPTION 1 | OPTION 2 | OPTION 3
  .075   |   .065   |   .043
library(microbenchmark)
library(data.table)

dt<-data.table(id=(1:100)[sample(10,size=1e6,replace=T)],var=c(1,0,NA)[sample(3,size=1e6,replace=T)],key=c("var"))

dt1 <- copy(dt)
dt2 <- copy(dt)
dt3 <- copy(dt)
dt4 <- copy(dt)

microbenchmark(times=10L,
               dt1[!is.na(var),.N,by=id][,max(N,na.rm=T),by=id],
               dt2[,length(var[!is.na(var)]),by=id],
               dt3[,sum(!is.na(var)),by=id],
               dt4[.(c(1,0)),.N,id,nomatch=0L])
# Unit: milliseconds
#                                                         expr      min       lq      mean    median        uq       max neval
#  dt1[!is.na(var), .N, by = id][, max(N, na.rm = T), by = id] 95.14981 95.79291 105.18515 100.16742 112.02088 131.87403    10
#                     dt2[, length(var[!is.na(var)]), by = id] 83.17203 85.91365  88.54663  86.93693  89.56223 100.57788    10
#                             dt3[, sum(!is.na(var)), by = id] 45.99405 47.81774  50.65637  49.60966  51.77160  61.92701    10
#                        dt4[.(c(1, 0)), .N, id, nomatch = 0L] 78.50544 80.95087  89.09415  89.47084  96.22914 100.55434    10