【发布时间】:2019-07-15 08:46:59
【问题描述】:
我目前有一个数据集,可以简化如下:
df <- data.frame(c(1,1,1,2,2,2,3,3,3),c(TRUE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,FALSE),
c(0,3,0,5,5,0,0,0,7), c("a","b","c","d","a","b","c","d","a"))
colnames(df) <- c("ID", "Status", "Number", "Letter")
ID Status Number Letter
1 1 TRUE 0 a
2 1 FALSE 3 b
3 1 TRUE 0 c
4 2 FALSE 5 d
5 2 FALSE 5 a
6 2 TRUE 0 b
7 3 TRUE 0 c
8 3 TRUE 0 d
9 3 FALSE 7 a
基本上,我想识别在 FALSE 之前出现 TRUE 的 ID。然后,我想用随后的 FALSE 行(即第 2、9、9 行)替换显示 TRUE 的行(即第 1、7、8 行)中的状态和编号。最终结果应如下所示:
ID Status Number Letter
1 1 FALSE 3 a
2 1 FALSE 3 b
3 1 TRUE 0 c
4 2 FALSE 5 d
5 2 FALSE 5 a
6 2 TRUE 0 b
7 3 FALSE 7 c
8 3 FALSE 7 d
9 3 FALSE 7 a
最后一列仅表明我还有其他特定于观察的变量,我不能简单地将整行替换为后续变量。
到目前为止,从这篇文章(R - Identify a sequence of row elements by groups in a dataframe)中,我设法获得了第一部分:
library(tidyverse)
extract <- df %>% group_by(ID) %>%
filter(ifelse(Status == FALSE,
lag(Status) == TRUE,
lead(Status) == FALSE))
# A tibble: 4 x 4
# Groups: ID [2]
ID Status Number Letter
<dbl> <lgl> <dbl> <fct>
1 1. TRUE 0. a
2 1. FALSE 3. b
3 3. TRUE 0. d
4 3. FALSE 7. a
对于如何从这里开始的任何帮助,我将不胜感激。我试图尽可能准确地说明我的问题,如果有任何不清楚的地方请告诉我。
编辑:按照@Henrik 的建议,我会为我的问题增加一些复杂性。这个数据集应该在这方面起作用:
df <- data.frame(c(1,1,1,2,2,2,3,3,3,4,4,4,4,4),c(TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,
FALSE,TRUE,FALSE,TRUE,FALSE,TRUE),
c(0,0,0,5,5,0,0,0,7,0,6,0,3,0), c("a","b","c","d","a","b","c","d","a","b",
"c","d","a","b"))
colnames(df) <- c("ID", "Status", "Number", "Letter")
> df
ID Status Number Letter
1 1 TRUE 0 a
2 1 TRUE 0 b
3 1 TRUE 0 c
4 2 FALSE 5 d
5 2 FALSE 5 a
6 2 TRUE 0 b
7 3 TRUE 0 c
8 3 TRUE 0 d
9 3 FALSE 7 a
10 4 TRUE 0 b
11 4 FALSE 6 c
12 4 TRUE 0 d
13 4 FALSE 3 a
14 4 TRUE 0 b
这是我提出的解决方案,但不适用于单个行(参见 12):
df2 <- df %>%
group_by(ID) %>%
mutate(Status2 = if (!all(Status)) replace(Status, cumsum(!Status) < 1, FALSE) else TRUE,
Number2 = if (!all(Status)) replace(Number, cumsum(!Status) < 1,
first(Number[Status == FALSE]))
else first(replace(Number, cumsum(!Status) < 1, Number[Status == TRUE])))
> df2
# A tibble: 14 x 6
# Groups: ID [4]
ID Status Number Letter Status2 Number2
<dbl> <lgl> <dbl> <fct> <lgl> <dbl>
1 1. TRUE 0. a TRUE 0.
2 1. TRUE 0. b TRUE 0.
3 1. TRUE 0. c TRUE 0.
4 2. FALSE 5. d FALSE 5.
5 2. FALSE 5. a FALSE 5.
6 2. TRUE 0. b TRUE 0.
7 3. TRUE 0. c FALSE 7.
8 3. TRUE 0. d FALSE 7.
9 3. FALSE 7. a FALSE 7.
10 4. TRUE 0. b FALSE 6.
11 4. FALSE 6. c FALSE 6.
12 4. TRUE 0. d TRUE 0.
13 4. FALSE 3. a FALSE 3.
14 4. TRUE 0. b TRUE 0.
第 12 行中 Number2 的结果应该与后面的行对应,即为 3。
【问题讨论】:
-
可以有多次运行
FALSE,因此每次运行TRUE对应的“数字”应该由下一次后续运行FALSE的值填充?例如。对于 ID = 1,有第四行(或更多)FALSE。 -
另外,
TRUE的原始“数字”总是0吗? -
@Hendrik,对于相同的 ID,可能会有 TRUE FALSE TRUE FALSE ... 的顺序。但是,对于每个 ID,所有 TRUE 行和所有 FALSE 行的 Number 都是相同的,所以在我看来,我们用哪一行 FALSE 替换它应该无关紧要。关于你的第二个问题:是的,在我的数据集中,所有状态为 TRUE 的行也将被分配数字 0。
-
"对于每个 ID,数字将与 [...] 所有 FALSE 行相同"。我认为情况并非如此,例如
FALSEID 4 中的数字:6 和 3。还请为第 12 行添加所需的结果。 -
@Henrik,抱歉。我是 SO 新手,仍然习惯于这个论坛的细节。没错,在我的原始数据集中,所有行(给定 ID)都具有相同的编号。但是,我在 ID = 4 中添加了通用性,因为将来我可能会遇到类似的场景,我需要这个技巧。感谢您帮助我改进我的帖子!
标签: r dataframe filter tidyverse