Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace value based on row number in r

Tags:

r

dplyr

I have a data frame looking kind of like this:

id <- c(1, 1, 1, 2, 2, 2, 3, 3, 3)
x <- c(1, 1, 0, 0, 1, 1, 1, 1, 1)
df <- data.frame(id, x)

I want to keep only the first value that = 1 for each id, otherwise I want it to = 0, looking like this:

     id     x
  <dbl> <dbl>
1     1     1
2     1     0
3     1     0
4     2     0
5     2     1
6     2     0
7     3     1
8     3     0
9     3     0

I've tried this code, but with no luck:

df %>% 
  group_by(id) %>%
  mutate(x = if (any(x == 1)) replace(x,
                                      row_number() != 1, 0) else x)
```

like image 232
johnny Avatar asked Jan 01 '23 03:01

johnny


2 Answers

Using replace you can do :

library(dplyr)
df %>% group_by(id) %>% mutate(y = replace(x, -match(1L, x), 0L))
#OR
#mutate(y = replace(x, which.max(x), 0L))

#     id     x     y
#  <dbl> <dbl> <dbl>
#1     1     1     1
#2     1     1     0
#3     1     0     0
#4     2     0     0
#5     2     1     1
#6     2     1     0
#7     3     1     1
#8     3     1     0
#9     3     1     0
like image 161
Ronak Shah Avatar answered Jan 02 '23 17:01

Ronak Shah


In base you can use ave to group by id and use ifelse with cumsum to replace after the first 1 with 0.

df$x <- ave(df$x, df$id, FUN=function(x) ifelse(cumsum(x)>1,0,x))
#df$x <- ifelse(ave(df$x, df$id, FUN=cumsum)>1, 0, df$x) #Alternativ
#df$x <- with(df, ifelse(ave(x, id, FUN=cumsum)>1, 0, x)) #Alternativ
df
#  id x
#1  1 1
#2  1 0
#3  1 0
#4  2 0
#5  2 1
#6  2 0
#7  3 1
#8  3 0
#9  3 0
like image 32
GKi Avatar answered Jan 02 '23 16:01

GKi