Удаление строк после события / болезни (1), произошедшего в R

#r #dplyr

#r #dplyr

Вопрос:

Я новичок в R, у меня есть набор идентификаторов ПАТЕНТОВ со статусом заболевания. Я хочу удалить строки после 1 появления статуса заболевания. Мой набор данных выглядит следующим образом

 ID  Date        Disease
123 02-03-2012  0
123 03-03-2013  1
123 04-03-2014  0
321 03-03-2015  1
423 06-06-2016  1
423 07-06-2017  1
543 08-05-2018  1
543 09-06-2019  0
645 08-09-2019  0
645 10-10-2018  0
645 11-10 -2012 0
  

Ожидаемый результат

 ID     Date       Disease
123  02-03-2012    0
123  03-03-2013    1
321  03-03-2015    1
423  06-06-2016    1
543  08-05-2018    1
645  08-09-2019    0
645  10-10-2018    0
645  11-10 -2012   0
  

Пожалуйста, предложите код, который возвращает ожидаемый результат.
Заранее спасибо!

Ответ №1:

dplyr Одним из способов было бы выбрать все строки, если они не Disease == 1 встречаются в ID , или выбрать строки только до первого 1.

 library(dplyr)
df %>%
  group_by(ID) %>%
  filter(if(any(Disease == 1)) row_number() <= match(1, Disease) else TRUE)

#     ID Date       Disease
#  <int> <chr>        <int>
#1   123 02-03-2012       0
#2   123 03-03-2013       1
#3   321 03-03-2015       1
#4   423 06-06-2016       1
#5   543 08-05-2018       1
#6   645 08-09-2019       0
#7   645 10-10-2018       0
#8   645 11-10-2012       0
  

данные

 df <- structure(list(ID = c(123L, 123L, 123L, 321L, 423L, 423L, 543L, 
543L, 645L, 645L, 645L), Date = c("02-03-2012", "03-03-2013", 
"04-03-2014", "03-03-2015", "06-06-2016", "07-06-2017", "08-05-2018", 
"09-06-2019", "08-09-2019", "10-10-2018", "11-10-2012"), Disease = c(0L, 
1L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L)), class = "data.frame", row.names = c(NA, 
-11L))
  

Ответ №2:

Это сделало бы это.

 set.seed(1012)

datas <- data_frame(ids = rep(1:3, each = 3), 
           times = runif(9, 0, 100),
           event = rep(c(0, 1, 0), 3)) %>%
  arrange(ids, times)

datas %>%
  group_by(ids) %>%
  mutate(lag(cumsum(event), default = 0) == 0)
  

Ответ №3:

Мы можем использовать cumsum для создания логического вектора для подмножества

 library(data.table)
setDT(df)[df[, .I[cumsum(cumsum(Disease)) <= 1], ID]$V1]
#    ID       Date Disease
#1: 123 02-03-2012       0
#2: 123 03-03-2013       1
#3: 321 03-03-2015       1
#4: 423 06-06-2016       1
#5: 543 08-05-2018       1
#6: 645 08-09-2019       0
#7: 645 10-10-2018       0
#8: 645 11-10-2012       0
  

Или с помощью dplyr

 library(dplyr)
df %>%
     group_by(ID) %>%
     filter(cumsum(cumsum(Disease)) <=1)
  

данные

 df <- structure(list(ID = c(123L, 123L, 123L, 321L, 423L, 423L, 543L, 
543L, 645L, 645L, 645L), Date = c("02-03-2012", "03-03-2013", 
"04-03-2014", "03-03-2015", "06-06-2016", "07-06-2017", "08-05-2018", 
"09-06-2019", "08-09-2019", "10-10-2018", "11-10-2012"), Disease = c(0L, 
1L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L)), class = "data.frame",
  row.names = c(NA, 
-11L))