我有一个带有 ID 列和另一列(Base/Promo)编码 1 或 0 的 df。我想创建第三个新列,其中包含一个计数器,如果(Base/Promo)中的值为 0 则进行计数,并且如果 (Base/Promo) 中的值为 1,则重置为 0,并在值为 0 时重新开始计数。此外,每当 ID 更改时,计数器都应重置。这是一个可重现的 df 以及输出应该是什么样子的示例:
df <- data.frame(ID = c(rep("1", 6), rep("2", 6),
rep("3", 6) rep("4", 6)),
response=c(0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,1,0))
df
期望的结果:
ID Base/Promo counter
1 1 0 1
2 1 0 2
3 1 0 3
4 1 1 0
5 1 0 1
6 1 0 2
7 2 1 0
8 2 0 1
9 2 0 2
10 2 0 3
11 2 0 4
12 2 1 0
13 3 0 1
14 3 0 2
15 3 0 3
16 3 1 0
17 3 1 0
18 3 0 1
19 4 0 1
20 4 0 2
21 4 0 3
22 4 1 0
23 4 1 0
24 4 0 1
我尝试使用以下代码:
df <- df %>%
group_by(ID, idx = cumsum("Base/Promo" == 1L)) %>%
mutate(counter= row_number()) %>%
ungroup %>%
select(-idx)
但这给了我以下结果:
ID Base/Promo counter
1 1 0 1
2 1 0 2
3 1 0 3
4 1 1 1
5 1 0 2
6 1 0 3
7 2 1 1
8 2 0 2
9 2 0 3
10 2 0 4
11 2 0 5
12 2 1 1
13 3 0 2
14 3 0 3
15 3 0 4
16 3 1 1
17 3 1 1
18 3 0 2
19 4 0 1
20 4 0 2
21 4 0 3
22 4 1 1
23 4 1 1
24 4 0 2
我希望你能帮助解决这个问题,因为我不知道还能尝试什么。如果我忽略了解决我问题的 SO 条目,如果您能指出我那里,那就太好了。非常感谢!!!
我们可以根据组的
counter
值来调整 first
值 :
library(dplyr)
df %>%
group_by(ID, grp = cumsum(response == 1L)) %>%
mutate(counter = if(first(response) == 1L) row_number() - 1
else row_number()) %>%
ungroup() %>%
dplyr::select(-grp)
# A tibble: 24 x 3
# ID response counter
# <chr> <dbl> <dbl>
# 1 1 0 1
# 2 1 0 2
# 3 1 0 3
# 4 1 1 0
# 5 1 0 1
# 6 1 0 2
# 7 2 1 0
# 8 2 0 1
# 9 2 0 2
#10 2 0 3
# … with 14 more rows
您可以使用 rle 生成序列并将结果与否定响应相乘。
df %>%
group_by(ID) %>%
mutate(x = with(rle(response), sequence(lengths)) * !response)
# A tibble: 24 x 3
# Groups: ID [4]
ID response x
<chr> <dbl> <int>
1 1 0 1
2 1 0 2
3 1 0 3
4 1 1 0
5 1 0 1
6 1 0 2
7 2 1 0
8 2 0 1
9 2 0 2
10 2 0 3
# ... with 14 more rows