有条件的按累计金额分组

时间:2021-02-14 15:35:04

标签: r dplyr cumsum

在这个数据框中:

df <- data.frame(
  ID = c("C", "B", "B", "B", NA, "C", "A", NA, "B", "B", "B")
)

我想使用具有两个条件的 cumsum 对行进行分组:(i) cumsum 不应该继续,如果 is.na(ID) 和 (ii) 它不应该继续,如果 next ID 值与前一个相同。我确实满足条件 (i):

df %>%
  group_by(grp = cumsum(!is.na(ID)))
# A tibble: 11 x 2
# Groups:   grp [9]
   ID      grp
   <chr> <int>
 1 C         1
 2 B         2
 3 B         3
 4 B         4
 5 NA        4
 6 C         5
 7 A         6
 8 NA        6
 9 B         7
10 B         8
11 B         9

但我也不知道如何实现条件 (ii) 以获得所需的结果

 1 C         1
 2 B         2
 3 B         2
 4 B         2
 5 NA        2
 6 C         3
 7 A         4
 8 NA        4
 9 B         5
10 B         5
11 B         5

我用这个试过了,但我不工作:

df %>%
  group_by(grp = cumsum(!is.na(ID) |!lag(ID,1) == ID))

3 个答案:

答案 0 :(得分:1)

使用zoo中的na.locf0填写NA,然后应用data.table中的rleid:

library(data.table)
library(zoo)

rleid(na.locf0(df$ID))
##  [1] 1 2 2 2 2 3 4 4 5 5 5

答案 1 :(得分:1)

使用 tidyrdplyr,您可以:

df %>%
 mutate(grp = fill(., ID) %>% pull(),
        grp = cumsum(grp != lag(grp, default = first(grp))))

     ID grp
1     C   0
2     B   1
3     B   1
4     B   1
5  <NA>   1
6     C   2
7     A   3
8  <NA>   3
9     B   4
10    B   4
11    B   4

答案 2 :(得分:1)

使用 rle

library(zoo)
with(rle(na.locf0(df$ID)), rep(seq_along(values), lengths))
#[1] 1 2 2 2 2 3 4 4 5 5 5