Home > Blockchain >  Apply ifelse without applying a for loop using R
Apply ifelse without applying a for loop using R

Time:05-08

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
  • Related