У меня есть данные в таблице data.table, которые я хочу суммировать. Тривиальный пример представлен ниже. Я начинаю с (переменной) n-столбцов (char) и некоторых групповых переменных.

Я могу заранее преобразовать их (nsk-vars в моем примере) в числовые / целые числа, если это так. Я хотел бы иметь возможность использовать строку имен столбцов для создания нового столбца, который представляет собой их сумму (nsk1-nsk3) и обрабатывать NA: s. Как мне сделать это разумным образом?

library(data.table)

x <- data.table(a    = c("GrpA", "GrpB"),
                nsk1 = c("1","3"),
                nsk2 = c(NA,"1"),
                nsk3 = c("3", "4"))

ClNamesStr <- colnames(x)
ClNamesStr <- ClNamesStr[grepl("^nsk", ClNamesStr)]

nskStrSum <- paste(ClNamesStr, collapse = "),as.numeric(")
nskStrSum <- paste("as.numeric(", nskStrSum, "), na.rm = TRUE")

Это та часть, над которой я хотел бы работать.

x[, nsk0 := sum(eval(nskStrSum)), by = a]

Желаемый результат будет следующим:

a    nsk1 nsk2 nsk3 nsk0
GrpA    1   NA    3    4
GrpB    3    1    4    8
1
ErrantBard 25 Ноя 2016 в 16:30

2 ответа

Лучший ответ

Вот один из способов.

x[, nsk0 := rowSums(sapply(.SD, function(i) as.numeric(i)), na.rm=TRUE),
  .SDcols=grep("^nsk", names(x)), by = a]

Который возвращается

x
      a nsk1 nsk2 nsk3 othr nsk0
1: GrpA    1   NA    3    a    4
2: GrpA    3    1    4    b    8

sapply просматривает выбранные переменные, преобразует каждую в числовую и возвращает матрицу. Эта матрица передается в rowSums, который суммирует значения в каждой строке и игнорирует NA. .SD - это сокращение для выбора таблицы data.table (кроме переменных, содержащихся в "by"). Однако переменные выбираются среди них с помощью .SDcols вместе с grep.

Некоторым data.tablers может не понравиться это решение, так как оно преобразует некоторые данные в матрицу. Однако в вашем случае это преобразование может потребоваться.

Я добавил дополнительную переменную "неприятности", чтобы показать, что она будет работать.

< Сильный > данные

x <- data.table(a    = c("GrpA", "GrpA"),
                nsk1 = c("1","3"),
                nsk2 = c(NA,"1"),
                nsk3 = c("3", "4"), 
                othr = letters[1:2])
1
lmo 25 Ноя 2016 в 14:05

Мы можем попробовать с Reduce после замены "NA" на 0.

i1 <- grep("nsk", names(x))
x[, nsk0 := Reduce(`+`, lapply(.SD, function(x) 
       as.numeric(replace(x, is.na(x), 0)))), .SDcols = i1]
x
#      a nsk1 nsk2 nsk3 othr nsk0
#1: GrpA    1   NA    3    a    4
#2: GrpA    3    1    4    b    8
1
akrun 25 Ноя 2016 в 14:46