Reputation: 197
I am trying to get the output below, but I do not know how to get it in R. This is the data I have:
ID PERIOD rating
8 0 3
8 1 3
8 2 2
8 3 F
8 4 3
8 5 F
8 6 1
9 0 2
9 1 2
9 2 1
Below is the output I want.
ID PERIOD rating
8 0 3
8 1 3
8 2 2
8 3 F
8 4 F
8 5 F
8 6 F
9 0 2
9 1 2
9 2 1
As you can see, As soon as the rating hit "F" for a particular ID then the rating should remain "F" for that ID. I do not know how to go about coding. Any help will be appreciated.
Upvotes: 1
Views: 44
Reputation: 886948
Here is an option
library(dplyr)
data %>%
group_by(ID) %>%
mutate(rating = replace(rating, row_number() > which(rating == "F")[1], "F" ))
# A tibble: 10 x 3
# Groups: ID [2]
# ID PERIOD rating
# <int> <int> <chr>
# 1 8 0 3
# 2 8 1 3
# 3 8 2 2
# 4 8 3 F
# 5 8 4 F
# 6 8 5 F
# 7 8 6 F
# 8 9 0 2
# 9 9 1 2
#10 9 2 1
Upvotes: 1
Reputation: 33498
Using data.table:
setDT(data)
data[, rating := ifelse(cumsum(rating == "F") >= 1, "F", rating), by = ID]
data
ID PERIOD rating
1: 8 0 3
2: 8 1 3
3: 8 2 2
4: 8 3 F
5: 8 4 F
6: 8 5 F
7: 8 6 F
8: 9 0 2
9: 9 1 2
10: 9 2 1
Where
data <- data.frame(
ID = c(8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L),
PERIOD = c(0L, 1L, 2L, 3L, 4L, 5L, 6L, 0L, 1L, 2L),
rating = c("3", "3", "2", "F", "3", "F", "1", "2", "2", "1"),
stringsAsFactors = FALSE
)
EDIT
Long story, but this could be made more concise:
data[, rating := ifelse(cumsum(rating == "F"), "F", rating), by = ID]
EDIT 2
As Ronak's suggests you could do something like the following using ave() that comes with base R:
data$rating <-
ifelse(ave(data$rating == "F", data$ID, FUN = cumsum), "F", data$rating)
Upvotes: 4