Накопительная сумма с потенциальными «перезагрузками» - PullRequest
3 голосов
/ 27 апреля 2020

У меня есть вектор чисел c, для которого я хочу вычислить своего рода совокупную сумму. Я говорю «сортировка», потому что стандартная сумма в основном равна cumsum[i] = cumsum[i-1] + x[i]. В этом случае, однако, мне нужно использовать cumsum[i] = max(cumsum[i-1] + x[i], x[i]).

То есть, если значение самого последнего элемента больше, чем кумулятивная сумма (что может произойти, если были предыдущие отрицательные значения, например, ), затем просто примите самый последний элемент.

Это, очевидно, можно сделать вручную с помощью тривиального for-l oop:

set.seed(1)
x <- runif(10, min = -1, max = 1)
csum <- rep(0, 10)
for(i in seq_along(x)) {
  if (i == 1) csum[i] <- x[i]

  csum[i] <- max(csum[i-1] + x[i], x[i])
}
x; csum
#>  [1] -0.4689827 -0.2557522  0.1457067  0.8164156 -0.5966361  0.7967794
#>  [7]  0.8893505  0.3215956  0.2582281 -0.8764275
#>  [1] -0.4689827 -0.2557522  0.1457067  0.9621223  0.3654862  1.1622655
#>  [7]  2.0516161  2.3732117  2.6314397  1.7550123

Создано в 2020-04- 27 пакетом Представить (v0.3.0)

Но есть ли способ сделать это, чтобы избежать for-l oop? Я бился головой, пытаясь придумать один из них, но просто не могу.

Если уместно, мой реальный случай применим это к кадру данных. Он будет сгруппирован, а затем я создам новый столбец с этой совокупной суммой для каждой группы. Но я доволен этой частью, я просто не могу понять, как очистить эту операцию.

1 Ответ

2 голосов
/ 27 апреля 2020

Мы можем использовать Reduce в base R

csum2 <- Reduce(function(u, v) max(u + v, v), x, accumulate = TRUE)

-проверку с выходом OP

identical(csum, csum2)
#[1] TRUE

Или другой вариант accumulate из purrr

library(purrr)
accumulate(x, ~  max(.x + .y, .y))
...