is.na(.SD)
создает логическую матрицу, затем мы конвертируем ее в data.table
, вместо этого ее можно зациклить с помощью lapply
, а затем сделать +
с Reduce
DATA[, NR := Reduce(`+`, lapply(.SD, is.na)),
.SDcols = paste0('var', 1:6), by = .(ID, day)]
Тесты
set.seed(24)
DATA <- data.table(ID = rep(1:500, each = 50), day = rep(1:25, length.out = 25000), var1= sample(c(1:5, NA), 25000, replace = TRUE),
var1= sample(c(1:40, NA), 25000, replace = TRUE), var2 = sample(c(1:25, NA), 25000, replace = TRUE), var3 = sample(c(1:35, NA), 25000, replace = TRUE),
var4= sample(c(1:100, NA), 25000, replace = TRUE), var5 = sample(c(1:50, NA), 25000, replace = TRUE), var6 = sample(c(1:10, NA), 25000, replace = TRUE))
DATA1 <- copy(DATA)
system.time(DATA[, NR := Reduce("+", data.table(!is.na(.SD))),.SDcols = c("var1","var2","var3","var4","var5","var6"),by=c("ID","day")])
# user system elapsed
# 6.451 0.148 5.535
system.time(DATA1[, NR := Reduce(`+`, lapply(.SD, is.na)), .SDcols = paste0('var', 1:6), by = .(ID, day)])
# user system elapsed
# 1.307 0.046 0.353
Или другой вариант rowSums
system.time(DATA1[, NR2 := rowSums(is.na(.SD)),
.SDcols = paste0('var', 1:6), by = .(ID, day)])
# user system elapsed
# 1.434 0.028 0.456