0

我有格式的数据

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"

对于每个主题,我想修改 status 的值,以便:a)在获得 test1 的最早(按测试日期)pos 或 neg 结果之前,它仍然是未知的;b) 当获得第一个 pos test1 结果时,该日期和之后的状态变为“in”,无论任何后续 test1 值如何;c) 如果 test1 在任何阳性结果之前出现阴性结果,则该日期和后续日期的状态变为“out”,直到获得任何阳性 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
4

1 回答 1

0

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
于 2017-03-27T16:06:06.383 回答