簡體   English   中英

R:data.table count!每行NA

[英]R: data.table count !NA per row

我試圖計算每行不包含NA的列數,並將該值放入該行的新列中。

示例數據:

library(data.table)

a = c(1,2,3,4,NA)
b = c(6,NA,8,9,10)
c = c(11,12,NA,14,15)
d = data.table(a,b,c)

> d 
    a  b  c
1:  1  6 11
2:  2 NA 12
3:  3  8 NA
4:  4  9 14
5: NA 10 15

我想要的輸出將包括一個新列num_obs ,其中包含每行非NA條目的數量:

    a  b  c num_obs
1:  1  6 11       3
2:  2 NA 12       2
3:  3  8 NA       2
4:  4  9 14       3
5: NA 10 15       2

我現在已經閱讀了好幾個小時,到目前為止,我所提出的最好的是循環遍歷行,我知道這在R或data.table中是不可取的。 我相信有更好的方法可以做到這一點,請賜教。

我糟糕的方式:

len = (1:NROW(d))
for (n in len) {
  d[n, num_obs := length(which(!is.na(d[n])))]
}

嘗試使用Reduce鏈接+調用:

d[, num_obs := Reduce(`+`, lapply(.SD,function(x) !is.na(x)))]

如果速度至關重要,那么您可以通過Ananda建議硬編碼被評估的列數來更多地了解一下:

d[, num_obs := 4 - Reduce("+", lapply(.SD, is.na))]

使用阿南達的較大data.table基准d從上面:

fun1 <- function(indt) indt[, num_obs := rowSums(!is.na(indt))][]
fun3 <- function(indt) indt[, num_obs := Reduce(`+`, lapply(.SD,function(x) !is.na(x)))][]
fun4 <- function(indt) indt[, num_obs := 4 - Reduce("+", lapply(.SD, is.na))][]

library(microbenchmark)
microbenchmark(fun1(copy(d)), fun3(copy(d)), fun4(copy(d)), times=10L)

#Unit: milliseconds
#          expr      min       lq     mean   median       uq      max neval
# fun1(copy(d)) 3.565866 3.639361 3.912554 3.703091 4.023724 4.596130    10
# fun3(copy(d)) 2.543878 2.611745 2.973861 2.664550 3.657239 4.011475    10
# fun4(copy(d)) 2.265786 2.293927 2.798597 2.345242 3.385437 4.128339    10

快速想到的兩個選項是:

d[, num_obs := sum(!is.na(.SD)), by = 1:nrow(d)][]
d[, num_obs := rowSums(!is.na(d))][]

第一種方法是通過創建每組只有一行的“組”( 1:nrow(d) )。 如果沒有它,它只會將整個表中的NA值相加。

第二個使用已經非常有效的基本R函數rowSums

以下是大數據的基准:

set.seed(1)
nrow = 10000
ncol = 15
d <- as.data.table(matrix(sample(c(NA, -5:10), nrow*ncol, TRUE), nrow = nrow, ncol = ncol))

fun1 <- function(indt) indt[, num_obs := rowSums(!is.na(indt))][]
fun2 <- function(indt) indt[, num_obs := sum(!is.na(.SD)), by = 1:nrow(indt)][]

library(microbenchmark)
microbenchmark(fun1(copy(d)), fun2(copy(d)))
# Unit: milliseconds
#           expr        min         lq       mean     median         uq      max neval
#  fun1(copy(d))   3.727958   3.906458   5.507632   4.159704   4.475201 106.5708   100
#  fun2(copy(d)) 584.499120 655.634889 684.889614 681.054752 712.428684 861.1650   100

順便說一下,empty []只是打印結果data.table 當您想要從“data.table”中的set* functions返回輸出時,這是必需的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM