我目前有一个数据集,可以简化如下:
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行)中的Status和Number。最终结果应如下所示:
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。
答案 0 :(得分:1)
您可以这样做:
library(dplyr)
df %>%
group_by(ID) %>%
mutate(flag = coalesce(Status == TRUE &
lead(Status == FALSE), FALSE)) %>%
group_by(ID, grp = cumsum(+(Status != lag(Status, default = "rndom")))) %>%
mutate(Status = ifelse(any(flag == TRUE), FALSE, Status)) %>% ungroup() %>%
select(-flag, -grp)
输出:
# A tibble: 9 x 4
ID Status Number Letter
<dbl> <lgl> <dbl> <fct>
1 1 FALSE 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 FALSE 0 c
8 3 FALSE 0 d
9 3 FALSE 7 a
答案 1 :(得分:1)
另一个选项,其中我们用replace
cumsum(!Status) < 1
TRUE
是FALSE
的所有值,即替换第一个FALSE
之前的所有值。
df %>%
group_by(ID) %>%
mutate(new_status = replace(Status, cumsum(!Status) < 1, FALSE))
# A tibble: 9 x 5
# Groups: ID [3]
# ID Status Number Letter new_status
# <dbl> <lgl> <dbl> <fct> <lgl>
#1 1 TRUE 0 a FALSE
#2 1 FALSE 3 b FALSE
#3 1 TRUE 0 c TRUE
#4 2 FALSE 5 d FALSE
#5 2 FALSE 5 a FALSE
#6 2 TRUE 0 b TRUE
#7 3 TRUE 0 c FALSE
#8 3 TRUE 0 d FALSE
#9 3 FALSE 7 a FALSE