Подтвердить что ты не робот

Строковые суммы по столбцам с определенным шаблоном в их имени

У меня есть data.table, подобный этому

dput(DT)
structure(list(ref = c(3L, 3L, 3L, 3L), nb = 12:15, i1 = c(3.1e-05, 
0.044495, 0.82244, 0.322291), i2 = c(0.000183, 0.155732, 0.873416, 
0.648545), i3 = c(0.000824, 0.533939, 0.838542, 0.990648), i4 = c(0.044495, 
0.82244, 0.322291, 0.393595)), .Names = c("ref", "nb", "i1", 
"i2", "i3", "i4"), row.names = c(NA, -4L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x0000000000320788>)

DT
#    ref nb       i1       i2       i3       i4
# 1:   3 12 0.000031 0.000183 0.000824 0.044495
# 2:   3 13 0.044495 0.155732 0.533939 0.822440
# 3:   3 14 0.822440 0.873416 0.838542 0.322291
# 4:   3 15 0.322291 0.648545 0.990648 0.393595

Теперь я хочу рассчитать суммы строк, но только включая столбцы, начинающиеся с "i" ( "i1", "i2" и т.д.)

Я использовал grep для создания вектора имен столбцов, которые нужно суммировать:

listCol <- colnames(DT)[grep("i", colnames(DT))]
listCol
# [1] "i1" "i2" "i3" "i4"

Затем я попытался перебрать столбцы:

DT$sum <- rep.int(0, nrow(DT))
for (i in listCol){
    DT$sum = DT$sum + DT[ , get(i)]
}

..., который дает желаемый результат:

DT
#    ref nb       i1       i2       i3       i4      sum
# 1:   3 12 0.000031 0.000183 0.000824 0.044495 0.045533
# 2:   3 13 0.044495 0.155732 0.533939 0.822440 1.556606
# 3:   3 14 0.822440 0.873416 0.838542 0.322291 2.856689
# 4:   3 15 0.322291 0.648545 0.990648 0.393595 2.355079

Как я могу улучшить свой код?


Дополнительный вопрос:

Этот подзапрос включает частично ответ на предыдущий:

Как избежать этой странной нотации:

myrowMeans = function (x){
    rowMeans(x, na.rm = TRUE)
}
DT[ , var := myrowMeans(.SD-myrowMeans(.SD)^2), .SDcols = grep("i", colnames(DT))]
4b9b3361

Ответ 1

Вы также можете попробовать Reduce

 DT[, Sum := Reduce(`+`, .SD), .SDcols=listCol][]
 #   ref nb       i1       i2       i3       i4      Sum
 #1:   3 12 0.000031 0.000183 0.000824 0.044495 0.045533
 #2:   3 13 0.044495 0.155732 0.533939 0.822440 1.556606
 #3:   3 14 0.822440 0.873416 0.838542 0.322291 2.856689
 #4:   3 15 0.322291 0.648545 0.990648 0.393595 2.355079

ПРИМЕЧАНИЕ: Если есть значения "NA", их следует заменить на "0" до Reduce i.e.

 DT[, Sum := Reduce(`+`, lapply(.SD, function(x) replace(x, 
                    which(is.na(x)), 0))), .SDcols=listCol][]

** Другое решение: ** используя rowSums

 DT[, Sum := rowSums(.SD, na.rm = TRUE), .SDcols = grep("i", names(DT))] 

Ответ 2

Используйте .SDcols, чтобы указать столбцы, затем возьмите rowSums. Используйте := для назначения новых столбцов:

DT[ ,sum := rowSums(.SD), .SDcols = grep("i", names(DT))]

Ответ 3

Решение dplyr должно было бы использовать mutate_ вместе с paste(listCol, collapse = "+"). Но я думаю, что решение Reduce работает быстрее.

DT <- mutate_(DT, sum = paste(listCol, collapse = "+"))