Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

R dataframe with special cumsum

I have a dateframe like this:

df <- data.frame(grp = c(rep("a", 5), rep("b", 5)), t = c(1:5, 1:5), value = c(-1, 5, 9, -15, 6, 5, 1, 7, -11, 9))

# Limits for desired cumulative sum (CumSum)

maxCumSum <- 8

minCumSum <- 0

What I would like to calculate is a cumulative sum of value by group (grp) within the values of maxCumSum and minCumSum. The respective table dt2 should look something like this:

grp     t       value   CumSum
a       1       -1      0
a       2       5       5
a       3       9       8
a       4       -15     0
a       5       6       6
b       1       5       5
b       2       1       6
b       3       7       8
b       4       -11     0
b       5       9       8

Think of CumSum as a water storage with has a certain maximum capacity and the level of which cannot sink below zero.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The normal cumsum does obviously not do the trick since there are no limitations to maximum or minimum. Has anyone a suggestion how to achieve this? In the real dataframe there are of course more than 2 groups and far more than 5 times.

Many thanks!

>Solution :

What you can do is create a function which calculate the cumsum until it reach the max value and start again at the min value like this:

df <- data.frame(grp = c(rep("a", 5), rep("b", 5)), t = c(1:5, 1:5), value = c(-1, 5, 9, -15, 6, 5, 1, 7, -11, 9))
library(dplyr)

maxCumSum <- 8
minCumSum <- 0
f <- function(x, y) max(min(x + y, maxCumSum), minCumSum)
df %>%
  group_by(grp) %>%
  mutate(CumSum = Reduce(f, value, 0, accumulate = TRUE)[-1])
#> # A tibble: 10 × 4
#> # Groups:   grp [2]
#>    grp       t value CumSum
#>    <chr> <int> <dbl>  <dbl>
#>  1 a         1    -1      0
#>  2 a         2     5      5
#>  3 a         3     9      8
#>  4 a         4   -15      0
#>  5 a         5     6      6
#>  6 b         1     5      5
#>  7 b         2     1      6
#>  8 b         3     7      8
#>  9 b         4   -11      0
#> 10 b         5     9      8

Created on 2022-07-04 by the reprex package (v2.0.1)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading