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)
```
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With