Назначить значение столбца (разделить применить объединить) на основе другого столбца

У меня есть данные формата

set.seed(40)
subject <- sample(c("mike", "john", "steve"), 20, replace = TRUE)
test1 <- sample(c("pos", "neg", "pos", "neg", "NA"), 20, replace = TRUE)
testdate <- Sys.Date() + sample(-1000:1000, 20, replace = FALSE)
mydf <- data.frame(subject, testdate, test1)
mydf$status <- "unknown"

Для каждого субъекта я хотел бы изменить значения статуса таким образом, чтобы: а) он оставался неизвестным до тех пор, пока не будет получен самый ранний (по дате тестирования) положительный или отрицательный результат для теста 1; b) когда получен первый результат pos test1, статус на эту дату и впоследствии становится «in» независимо от любых последующих значений test1; c) если отрицательный результат возникает для test1 до любого положительного результата, статус становится «вне» для этой и последующих дат до тех пор, пока не будет получен положительный результат test1. Открыт для всех решений. Я экспериментирую с dplyr и меня особенно заинтересует решение на основе dplyr.

Результат будет

subject testdate    test1   status
john    2014-11-20  neg negative
john    2015-07-29  neg negative
john    2015-11-10  neg negative
john    2017-04-08  neg negative
john    2018-09-18  NA  negative
mike    2014-09-01  pos positive
mike    2014-10-14  neg positive
mike    2015-03-22  neg positive
mike    2016-09-15  pos positive
mike    2017-08-18  neg positive
mike    2017-12-20  pos positive
mike    2018-09-06  NA  positive
mike    2019-09-02  neg positive
steve   2015-06-21  neg negative
steve   2016-01-03  pos positive
steve   2016-03-12  neg positive
steve   2017-06-26  neg positive
steve   2017-12-02  neg positive
steve   2018-12-20  pos positive
steve   2019-06-20  pos positive

person marcel    schedule 25.03.2017    source источник
comment
не могли бы вы добавить ожидаемый результат?   -  person yeedle    schedule 26.03.2017


Ответы (1)


Это относительно просто с group_by и mutate.

Во-первых, измените результаты теста, чтобы они были фактором. Это позволяет «ранжировать» их, чтобы мы могли определить, какой был «наивысший» результат. Поскольку вы хотите, чтобы результаты были «Отсутствующие», «Отрицательные», «Положительные», установите уровни в следующем порядке:

mydf$test1 <-
  factor(mydf$test1
         , levels = c("NA", "neg", "pos")
         , ordered = TRUE)

Затем создайте вектор меток, которые вы хотите использовать, когда произойдет каждое из вышеперечисленных действий. В тексте вы сказали, что хотите войти / выйти, но желаемый результат использует отрицательный / положительный. Если вы хотите изменить метки, это должно быть легко сделать здесь:

statusLevels <-
  c("Unknown", "Negative", "Positive")

Наконец, мы можем применить это к данным. Во-первых, отсортируйте результаты по дате, чтобы убедиться, что результаты теста проверены в правильном порядке (я также сортирую по темам, чтобы результаты были понятны и соответствовали вашему запросу). Затем сгруппируйте по теме. Наконец, mutate, чтобы создать нужный столбец. Здесь он проверяет "самое большое" тестовое значение на данный момент (поэтому мы преобразовали его в коэффициент) и дает нам соответствующий уровень статуса:

mydf %>%
  arrange(subject, testdate) %>%
  group_by(subject) %>%
  mutate(status = statusLevels[cummax(as.numeric(test1))])

Возврат:

   subject   testdate test1   status
     <chr>     <date> <ord>    <chr>
1     john 2014-11-21   neg Negative
2     john 2015-07-30   neg Negative
3     john 2015-11-11   neg Negative
4     john 2017-04-09   neg Negative
5     john 2018-09-19    NA Negative
6     mike 2014-09-02   pos Positive
7     mike 2014-10-15   neg Positive
8     mike 2015-03-23   neg Positive
9     mike 2016-09-16   pos Positive
10    mike 2017-08-19   neg Positive
11    mike 2017-12-21   pos Positive
12    mike 2018-09-07    NA Positive
13    mike 2019-09-03   neg Positive
14   steve 2015-06-22   neg Negative
15   steve 2016-01-04   pos Positive
16   steve 2016-03-13   neg Positive
17   steve 2017-06-27   neg Positive
18   steve 2017-12-03   neg Positive
19   steve 2018-12-21   pos Positive
20   steve 2019-06-21   pos Positive
person Mark Peterson    schedule 27.03.2017
comment
Спасибо за это очень чистое решение - для меня хорошая возможность узнать об использовании ранжированных факторов. - person marcel; 28.03.2017