Кумулятивные суммы подмножеств столбцов в data.table с использованием .SD - PullRequest
2 голосов
/ 21 февраля 2020

У меня есть data.table с парой идентификаторов и длинным списком числовых столбцов, которые представляют вероятности, которые складываются по одному для каждой строки. Минимальный пример:

library(data.table)
DT = data.table(
  ID = c("a","b","c"),
  ProbA = c(0.6, 0.25, 0.55),
  ProbB = c(0.25, 0.55, 0.35),
  ProbC = c(0.15, 0.2, 0.1)
);DT

   ID ProbA ProbB ProbC
1:  a  0.60  0.25  0.15
2:  b  0.25  0.55  0.20
3:  c  0.55  0.35  0.10

Теперь я хочу добавить столбцы для каждой вероятности с совокупной вероятностью относительно индекса их столбца, например:

  ID ProbA ProbB ProbC ProbAcum ProbBcum ProbCcum
1:  a  0.60  0.25  0.15     0.60     0.85        1
2:  b  0.25  0.55  0.20     0.25     0.80        1
3:  c  0.55  0.35  0.10     0.55     0.90        1

Я пробовал это с lapply и подмножеством столбцов:

Probcols <- c("ProbA", "ProbB", "ProbC")
DT[, (paste0(Probcols,"cum")):=lapply(.SD, function(x){rowSums(DT[, 2:which(Probcols==x)])}), .SDcols=Probcols]

можно ли как-нибудь заставить эту работу работать?

Ответы [ 2 ]

3 голосов
/ 21 февраля 2020

Вы можете попробовать это (я использую подход Base R):

do.call('cbind', Reduce(`+`, DT[,2:4], accumulate = TRUE))

Использование Reduce with накапливать = TRUE выполняет накопительную часть, все, что вам нужно, это заботиться о том, чтобы выбранные здесь столбцы быть нумерацией c например, я взял 2: 4 для выбора нумерации c только для столбца

Вы можете сделать привязку к существующему фрейму данных:

cbind(DT, do.call('cbind', Reduce(`+`, DT[,2:4], accumulate = TRUE))
do.call('cbind', Reduce(`+`, DT[,2:4], accumulate = TRUE))
     [,1] [,2] [,3]
[1,] 0.60 0.85    1
[2,] 0.25 0.80    1
[3,] 0.55 0.90    1

В случае, если вы сохраните имена как:

nm1 <- names(DT)
nm2 <- paste0(names(DT)[-1], '_Accum')
DT <- cbind(DT, do.call('cbind', Reduce(`+`, DT[,2:4], accumulate = TRUE)))
names(DT) <- c(nm1,nm2)

ИЛИ , используя подход data.table, используя оригинальные DT и nm2 <- paste0(names(DT)[-1], '_Accum')

DT[, c(nm2) := Reduce(`+`, .SD[,2:4], accumulate = TRUE)]

Ouput :

  ID ProbA ProbB ProbC ProbA_Accum ProbB_Accum ProbC_Accum
1:  a  0.60  0.25  0.15        0.60        0.85           1
2:  b  0.25  0.55  0.20        0.25        0.80           1
3:  c  0.55  0.35  0.10        0.55        0.90           1
>
2 голосов
/ 21 февраля 2020

Один вариант с rowCumsums

library(matrixStats)    
DT[, paste0(names(DT)[-1], "Accum"):= asplit(rowCumsums(as.matrix(.SD[, 
      -1, with = FALSE])), 2)]
DT
#   ID ProbA ProbB ProbC ProbAAccum ProbBAccum ProbCAccum
#1:  a  0.60  0.25  0.15       0.60       0.85          1
#2:  b  0.25  0.55  0.20       0.25       0.80          1
#3:  c  0.55  0.35  0.10       0.55       0.90          1
...