我有一个像这样的数据集:
id <- c(1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2)
value <- c("x","x","y",NA,NA,"x",NA,"y",
"y","y",NA,"x","x",NA,"x","x")
id value
1 1 x
2 1 x
3 1 y
4 1 <NA>
5 1 <NA>
6 1 x
7 1 <NA>
8 1 y
9 2 y
10 2 y
11 2 <NA>
12 2 x
13 2 x
14 2 <NA>
15 2 x
16 2 x
我希望对每次值变化进行滚动计数,但跳过 NA。
我理想的输出是这样的:
id value rolling_count
1 1 x 1
2 1 x 1
3 1 y 2
4 1 <NA> NA
5 1 <NA> NA
6 1 x 3
7 1 <NA> NA
8 1 y 4
9 2 y 1
10 2 y 1
11 2 <NA> NA
12 2 x 2
13 2 x 2
14 2 <NA> NA
15 2 x 2
16 2 x 2
我目前已经尝试使用 rle() 进行以下操作,它可以获取滚动计数,但将单个或一组 NA 视为计数的一部分,并生成下面的输出。已经很接近了,但还没有完全实现。
df %>%
group_by(id) %>%
mutate(failed_rolling_count = with(rle(value)), rep(seq_along(lengths), lengths))
id value failed_rolling_count
1 1 x 1
2 1 x 1
3 1 y 2
4 1 <NA> 3
5 1 <NA> 3
6 1 x 4
7 1 <NA> 5
8 1 y 6
9 2 y 1
10 2 y 1
11 2 <NA> 2
12 2 x 3
13 2 x 3
14 2 <NA> 4
15 2 x 5
16 2 x 5
非常感谢任何提示!
dplyr
1.1.0 版本引入了 consecutive_id()
,因此您不再需要 rle
。下面是添加行号、将 NA 排序到底部、添加滚动计数,然后排序回原始行顺序的方法。当然,如果您愿意,可以删除末尾的 row
列。
df |>
mutate(row = row_number()) |>
arrange(is.na(value), row) |>
mutate(
rolling_count = ifelse(is.na(value), NA, consecutive_id(value)),
.by = "id"
) |>
arrange(row)
# id value row rolling_count
# 1 1 x 1 1
# 2 1 x 2 1
# 3 1 y 3 2
# 4 1 <NA> 4 NA
# 5 1 <NA> 5 NA
# 6 1 x 6 3
# 7 1 <NA> 7 NA
# 8 1 y 8 4
# 9 2 y 9 1
# 10 2 y 10 1
# 11 2 <NA> 11 NA
# 12 2 x 12 2
# 13 2 x 13 2
# 14 2 <NA> 14 NA
# 15 2 x 15 2
# 16 2 x 16 2