#r #dplyr #cumsum
#r #dplyr #сумма
Вопрос:
В этом фрейме данных:
df <- data.frame(
ID = c("C", "B", "B", "B", NA, "C", "A", NA, "B", "B", "B")
)
Я хотел бы сгруппировать строки, используя cumsum
два условия: (i) cumsum
не должно продолжаться, если is.na(ID)
и (ii) оно не должно продолжаться, если следующее 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))
Ответ №1:
Используйте na.locf0 из zoo для заполнения NAs, а затем примените rleid из data.table:
library(data.table)
library(zoo)
rleid(na.locf0(df$ID))
## [1] 1 2 2 2 2 3 4 4 5 5 5
Ответ №2:
Используя tidyr
и dplyr
, вы могли бы сделать:
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
Ответ №3:
Используя 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