I have one vector
x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11)
Now, a vector y needs to accumulate if vector x is negative and the opposite when positive until back to zero:
y <- c(0,0,-4,-10,-12,-11,-7,-5,-8,-14,-15,-7,0,0,-6,-17)
Here are the conditions to be respected:
The cumulative sum of negative and positive values as long as the sum is less than 0
If the sum is positive, the cumulative sum is stopped until the following negative values are reached.
When the sum becomes positive, the printed value is 0.
Thanks for help!
I think that this calculation is not trivial to vectorise because the elements depend in a non-trivial way on previous elements, so the best approach might simply be to use a loop:
x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11)
y <- pmin(x,0) # gives us the first element correctly, and the correct vector length
for (i in seq_along(x[-1])) y[i+1] <- pmin(y[i] + x[i+1], 0)
y
# [1] 0 0 -4 -10 -12 -11 -7 -5 -8 -14 -15 -7 0 0 -6 -17
x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11)
for (i in seq_along(x)) { x[i] = ifelse(sum(x[(i-1):i]) > 0, 0, sum(x[(i-1):i])) }
x
# [1] 0 0 -4 -10 -12 -11 -7 -5 -8 -14 -15 -7 0 0 -6 -17
Another approach is using Reduce like this:
Reduce(function(u, v) ifelse(sum(c(u, v)) > 0, 0, sum(c(u, v))), x, accumulate = T, init = x[1])[-1]
# [1] 0 0 -4 -10 -12 -11 -7 -5 -8 -14 -15 -7 0 0 -6 -17
If you want to apply that process to each column you can use this example:
# example dataset
df = data.frame(x = c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11),
y = c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11),
z = c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11))
# function to update columns
UpdateColumn = function(x) {
for (i in seq_along(x)) { x[i] = ifelse(sum(x[(i-1):i]) > 0, 0, sum(x[(i-1):i])) }
x
}
# apply function to each column
# save as data frame
data.frame(sapply(df, UpdateColumn))
# x y z
# 1 0 0 0
# 2 0 0 0
# 3 -4 -4 -4
# 4 -10 -10 -10
# 5 -12 -12 -12
# 6 -11 -11 -11
# 7 -7 -7 -7
# 8 -5 -5 -5
# 9 -8 -8 -8
# 10 -14 -14 -14
# 11 -15 -15 -15
# 12 -7 -7 -7
# 13 0 0 0
# 14 0 0 0
# 15 -6 -6 -6
# 16 -17 -17 -17
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With