根据另一列分配列值(拆分应用组合)
Assign column value (split apply combine) based on another column
我有
格式的数据
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"
对于每个主题,我想修改状态值,以便:a) 在获得 test1 的最早(按测试日期)pos 或 neg 结果之前,它仍然是未知的; b) 当获得第一个 pos test1 结果时,无论任何后续的 test1 值如何,该日期及之后的状态都会变为“in”; 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
这对于 group_by
和 mutate
来说相对简单。
首先修改测试结果为一个因素。这使它们成为 "ranked",这样我们就可以知道 "highest" 结果是什么。因为您希望结果为 "Missing"、"Negative"、"Positive",请按以下顺序设置级别:
mydf$test1 <-
factor(mydf$test1
, levels = c("NA", "neg", "pos")
, ordered = TRUE)
接下来,创建一个向量,其中包含您在上述各项发生时要使用的标签。在文本中,您说您想要 in/out,但所需的输出使用 Negative/Positive。如果你想改变标签,在这里应该很容易做到:
statusLevels <-
c("Unknown", "Negative", "Positive")
最后,我们可以将其应用于数据。首先,按日期排序,以确保测试结果按正确的顺序检查(我也是按主题排序,以使结果清晰并符合您的要求)。然后,按主题分组。最后,mutate
创建你想要的列。在这里,它检查到目前为止的 "biggest" 测试值(因此我们转换为一个因子)并为我们提供匹配的状态级别:
mydf %>%
arrange(subject, testdate) %>%
group_by(subject) %>%
mutate(status = statusLevels[cummax(as.numeric(test1))])
Returns:
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
我有
格式的数据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"
对于每个主题,我想修改状态值,以便:a) 在获得 test1 的最早(按测试日期)pos 或 neg 结果之前,它仍然是未知的; b) 当获得第一个 pos test1 结果时,无论任何后续的 test1 值如何,该日期及之后的状态都会变为“in”; 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
这对于 group_by
和 mutate
来说相对简单。
首先修改测试结果为一个因素。这使它们成为 "ranked",这样我们就可以知道 "highest" 结果是什么。因为您希望结果为 "Missing"、"Negative"、"Positive",请按以下顺序设置级别:
mydf$test1 <-
factor(mydf$test1
, levels = c("NA", "neg", "pos")
, ordered = TRUE)
接下来,创建一个向量,其中包含您在上述各项发生时要使用的标签。在文本中,您说您想要 in/out,但所需的输出使用 Negative/Positive。如果你想改变标签,在这里应该很容易做到:
statusLevels <-
c("Unknown", "Negative", "Positive")
最后,我们可以将其应用于数据。首先,按日期排序,以确保测试结果按正确的顺序检查(我也是按主题排序,以使结果清晰并符合您的要求)。然后,按主题分组。最后,mutate
创建你想要的列。在这里,它检查到目前为止的 "biggest" 测试值(因此我们转换为一个因子)并为我们提供匹配的状态级别:
mydf %>%
arrange(subject, testdate) %>%
group_by(subject) %>%
mutate(status = statusLevels[cummax(as.numeric(test1))])
Returns:
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