Conditional cumsum with reset when accumulating and substracting at once
Here is one way you might do this:
ve$DO <- Reduce(function(x,y) pmax(x + y, 0), with(ve, V2-V3*(V1 > 0)), accumulate = TRUE)
ve
V1 V2 V3 DO
1 -2 6 0 6
2 4 0 5 1
3 3 0 8 0
4 -5 1 0 1
5 -5 0 0 1
6 -7 2 0 3
7 -8 3 0 6
8 -2 5 0 11
9 -3 7 0 18
10 -5 7 0 25
11 -7 8 0 33
12 -8 2 0 35
13 -9 0 0 35
14 -2 0 7 35
15 1 0 9 26
16 2 0 12 14
17 4 0 0 14
Equivalent using purrr/dplyr
:
library(purrr)
library(dplyr)
ve %>%
mutate(DO = accumulate(V2-V3*(V1 > 0), .f = ~pmax(.x + .y, 0)))
cumsum with a condition to restart in R
You may use cumsum
to create groups as well.
library(dplyr)
df <- df %>%
group_by(group = cumsum(dplyr::lag(port == 0, default = 0))) %>%
mutate(cumsum_G = cumsum(G)) %>%
ungroup
df
# inv ass port G group cumsum_G
# <chr> <chr> <int> <int> <dbl> <int>
#1 i x 2 1 0 1
#2 i x 2 0 0 1
#3 i x 0 1 0 2
#4 i x 3 0 1 0
#5 i x 3 1 1 1
You may remove the group
column from output using %>% select(-group)
.
data
df <- structure(list(inv = c("i", "i", "i", "i", "i"), ass = c("x",
"x", "x", "x", "x"), port = c(2L, 2L, 0L, 3L, 3L), G = c(1L,
0L, 1L, 0L, 1L)), class = "data.frame", row.names = c(NA, -5L))
How do I fix a cumulative sum in R when dealing with negative values
We can calculate the increments with diff
and use pmax
to set all negative increments to 0. Then we cumsum
this corrected increment:
df %>%
group_by(player) %>%
mutate(
increment = c(first(LifeTimeCumulative), pmax(diff(LifeTimeCumulative), 0)),
corrected = cumsum(increment)
) %>%
ungroup()
# # A tibble: 12 × 6
# player date LifeTimeCumulative LifeTimeCumulativeCorrect increment corrected
# <fct> <date> <dbl> <dbl> <dbl> <dbl>
# 1 A 2022-01-01 0 0 0 0
# 2 A 2022-01-02 2 2 2 2
# 3 A 2022-01-03 0 2 0 2
# 4 A 2022-01-04 1 3 1 3
# 5 B 2022-01-01 0 0 0 0
# 6 B 2022-01-02 2 2 2 2
# 7 B 2022-01-03 2 2 0 2
# 8 B 2022-01-04 1 2 0 2
# 9 C 2022-01-01 1 1 1 1
# 10 C 2022-01-02 2 2 1 2
# 11 C 2022-01-03 2 2 0 2
# 12 C 2022-01-04 0 2 0 2
Cumulative sum with potential resets
We can use Reduce
in base R
csum2 <- Reduce(function(u, v) max(u + v, v), x, accumulate = TRUE)
-checking with OP's output
identical(csum, csum2)
#[1] TRUE
Or another option is accumulate
from purrr
library(purrr)
accumulate(x, ~ max(.x + .y, .y))
dplyr / R cumulative sum with reset
I think you can use accumulate()
here to help. And i've also made a wrapper function to use for different thresholds
sum_reset_at <- function(thresh) {
function(x) {
accumulate(x, ~if_else(.x>=thresh, .y, .x+.y))
}
}
tib %>% mutate(c = sum_reset_at(5)(a))
# t a c
# <dbl> <dbl> <dbl>
# 1 1 2 2
# 2 2 3 5
# 3 3 1 1
# 4 4 2 3
# 5 5 2 5
# 6 6 3 3
tib %>% mutate(c = sum_reset_at(4)(a))
# t a c
# <dbl> <dbl> <dbl>
# 1 1 2 2
# 2 2 3 5
# 3 3 1 1
# 4 4 2 3
# 5 5 2 5
# 6 6 3 3
tib %>% mutate(c = sum_reset_at(6)(a))
# t a c
# <dbl> <dbl> <dbl>
# 1 1 2 2
# 2 2 3 5
# 3 3 1 6
# 4 4 2 2
# 5 5 2 4
# 6 6 3 7
Cumsum with criteria in R
A looping (and less fast) alternative to cumsum
is Reduce(`+`, x, accumulate = TRUE)
. However, this Reduce
approach can then be modified to your resetting cumulative sum:
Reduce(function(x, y) if (x + y > 0) x + y else 0, d, accumulate = TRUE)
Related Topics
How Do We Plot Images at Given Coordinates in R
Using Functions and Environments
Changing Styles When Selecting and Deselecting Multiple Polygons with Leaflet/Shiny
Remove Weekend Data in a Dataframe
R: Replacing Nas in a Data.Frame with Values in the Same Position in Another Dataframe
How to Efficiently Read the First Character from Each Line of a Text File
Error in Get(As.Character(Fun), Mode = "Function", Envir = Envir)
Displaying Image on Point Hover in Plotly
Extracting Orthogonal Polynomial Coefficients from R's Poly() Function
Boxplot, How to Match Outliers' Color to Fill Aesthetics
Remove Certain Legend Variables and Legend Values from Ggplot2
Dual Y Axis (Second Axis) Use in Ggplot2