ve <- c(17, -9, 9, -17, 17, -17, 11, -9, 16, -18, 17, 0, 0, -18, 17, 0, 0, -17, 14, -14, 17, -2, 0, -15, 9, -9, 17, -16, 16, -17, 17, -17, 17, -17, 17, -17, 17, -
Here is an iterative solution. I can't think of how to do this vectorized/using dplyr
without multiple passes over the data, but I'm sure someone else will:
ve_csum = numeric(length(ve))
current_total = 0
for (i in 1:length(ve)) {
if (is.na(ve[i])) {
ve_csum[i] = current_total
next
}
current_total = current_total + ve[i]
if (current_total < 0) {
current_total = 0
}
ve_csum[i] = current_total
}
result = data.frame(ve, ve_csum)
> df$calc=ifelse(cumsum(df$ve)<0,0,cumsum(df$ve))
We can replace
the NA values with 0 and use cumsum
library(dplyr)
df1 <- df %>%
group_by(grp = cumsum(lag(cumsum(replace(ve, is.na(ve), 0)) < 0, default = TRUE))) %>%
mutate(calc = cumsum(replace(ve, is.na(ve), 0)), calc = replace(calc, calc < 0, 0)) %>%
ungroup() %>%
select(-grp)
head(df1, 15)
# A tibble: 15 x 2
# ve calc
# <dbl> <dbl>
# 1 17 17
# 2 -9 8
# 3 9 17
# 4 -17 0
# 5 17 17
# 6 -17 0
# 7 11 11
# 8 -9 2
# 9 16 18
#10 -18 0
#11 17 17
#12 0 17
#13 0 17
#14 -18 0
#15 17 17
Not using dplyr
, but this should work:
ve = as.data.frame(ve)
ve = na.omit(ve)
ve$cumS = 0
ve$cumS[1] = ve$ve[1]
for (i in 2 : length(ve$ve)) {
ve$cumS[i] = ifelse((ve$cumS[i - 1] + ve$ve[i]) < 0,
0, (ve$cumS[i - 1] + ve$ve[i]))
}