2015-04-16 17 views
13

Đôi khi tôi cần đếm số thành phần không phải là NA trong một hoặc một cột khác trong data.table của mình. Cách tốt nhất để làm như vậy là data.table?Đo đếm hiệu quả các yếu tố phi NA trong dữ liệu. Có thể

Đối concreteness, chúng ta hãy làm việc với điều này:

DT <- data.table(id = sample(100, size = 1e6, replace = TRUE), 
       var = sample(c(1, 0, NA), size = 1e6, replace = TRUE), key = "id") 

Việc đầu tiên mà nói đến cái tâm của tôi làm việc như thế này:

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

Nhưng điều này có thiếu sót đáng tiếc rằng N không được giao vào bất kỳ hàng nào thiếu var, nghĩa là DT[is.na(var), N] = NA.

Vì vậy, tôi làm việc xung quanh này bằng cách phụ thêm:

DT[!is.na(var), N:= .N, by = id][ , N := max(N, na.rm = TRUE), by = id] #OPTION 1 

Tuy nhiên, tôi không chắc chắn đây là cách tiếp cận tốt nhất; một lựa chọn Tôi nghĩ đến và một đề xuất bởi các analog để this câu hỏi cho data.frame s sẽ là:

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

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

So sánh thời gian tính toán trong số này (trung bình hơn 100 thử nghiệm), dường như cuối cùng là nhanh nhất:

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

Có ai biết cách nhanh hơn cho data.table không?

Trả lời

7

Có tùy chọn thứ 3 có vẻ là tùy chọn tốt nhất. Tôi đã thêm một số khác chỉ hợp lệ nếu bạn xem xét thay đổi khóa dữ liệu của mình. Có thể từ id thành var, nhưng vẫn tùy chọn 3 là dữ liệu nhanh nhất trên dữ liệu của bạn.

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 
+2

@MichaelChirico, có một cái nhìn tại [Keys và tìm kiếm dựa tập con nhị phân] (https://github.com/Rdatatable/data.table/wiki/Getting-started) (và để chúng tôi biết nếu bạn tìm thấy một cái gì đó không rõ ràng/được thêm vào [ở đây] (https://github.com/Rdatatable/data.table/issues/944) – Arun

+0

Có một tùy chọn khác: 'dt5 [,. N [! is. na (var)], bởi = id] '- thứ ba nhanh nhất trên hệ thống của tôi và khá hơn rất nhiều so với tùy chọn 1 và 2. Đối với một số lý do tùy chọn 3 tạo ra phản hồi nhị phân (0,1) thay vì đếm nếu nhiều hơn một ' 'biến được sử dụng. Tùy chọn được đề xuất 5 cho số đếm chính xác. –

Các vấn đề liên quan