'Apply ifelse without applying a for loop using R
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)?
Update
My actual problem is more general than the situation I explained earlier. I apologize for the confusion. My data can have more than one negative values like in the given example:

Solution 1:[1]
A dplyr solution with cumsum() determining the position where v1 < 0:
library(dplyr)
data %>%
mutate(v2 = ifelse(row_number() < which.max(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
If the data have more than one negative values:
data <- data.frame(v1 = c(0, 29, 32, 60, -30, 31, -31, 31),
v2 = c(0, 0, 0, 1, 0, 1, 0, 1))
My code gives (result column):
v1 v2 result
1 0 0 0
2 29 0 0
3 32 0 0
4 60 1 0
5 -30 0 0
6 31 1 0
7 -31 0 0
8 31 1 1
Solution 2:[2]
Last Update:
v1= c(0 , 29, 32 , 60, -30 , 31, -31, 31 )
v2=c(0, 0, 0, 1, 0, 1,0,1)
data=data.frame(v1,v2)
data %>%
group_by(group_id = lag(cumsum(v1<0), default=0)) %>%
mutate(v2 = lag(cumsum(v1<0), default = min(v2))) %>%
ungroup() %>%
select(-group_id)
v1 v2
<dbl> <dbl>
1 0 0
2 29 0
3 32 0
4 60 0
5 -30 0
6 31 0
7 -31 0
8 31 1
First answer:
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
Solution 3:[3]
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
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Oliver |
