I have data with 2 columns like this :
v1 = c(0, 29, 32, 29, 32, 28, -59, 30)
v2 = c(0, 0, 0, 0, 1, 1, 0, 1)
data = data.frame(v1, v2)
v1 v2
1 0 0
2 29 0
3 32 0
4 29 0
5 32 1
6 28 1
7 -59 0
8 30 1
I want to change the values of the column v2 as follows: if the value of v1 is negative, then change all previous 1s of v2 to 0. I can do this using applying a for loop using R
. Is there a way to do the same thing without applying a for loop (probably using dplyr
package)?
CodePudding user response:
A base
solution with cumsum()
determining the position where v1 < 0
:
within(data, v2 <- ifelse(!cumsum(v1 < 0), 0, v2))
v1 v2
1 0 0
2 29 0
3 32 0
4 29 0
5 32 0
6 28 0
7 -59 0
8 30 1
Its dplyr
equivalent:
library(dplyr)
data %>%
mutate(v2 = ifelse(!cumsum(v1 < 0), 0, v2))
CodePudding user response:
No need for something fancy, find the last 1
and overwrite all prior 1's as zero in 2 steps
# Find last one
lastO <- max(which(data$v1))
if(length(last0)){
# Overwrite all v2 where v2 == 1 and the row is prior to the last row in v1
data$v2[data$v2 == 1 & seq.int(lastO) < lastO] <- 0
}
CodePudding user response:
We could use lag
together with cumsum
:
library(dplyr)
data %>%
mutate(v2 = lag(cumsum(v1<0), default = 0))
v1 v2
1 0 0
2 29 0
3 32 0
4 29 0
5 32 0
6 28 0
7 -59 0
8 30 1