There are a lot of very good solutions here, but I would like to note that some do not give the same result as data.table::rleid()
when the data has NAs
. Keep in mind that data.table::rleid()
increments everytime there is a change, including NAs
.
Data:
library(data.table)
library(dplyr)
# Data
DT2 = data.table(grp=rep(c("A", "B", NA, "C", "A", NA, "B", NA), c(2, 2, 2, 3, 1, 1, 2, 1)), value=1:14)
df <- data.frame(DT2)
# data.table reild
DT2[, rleid := rleid(DT2$grp)]
DT2
#> grp value rleid
#> 1: A 1 1
#> 2: A 2 1
#> 3: B 3 2
#> 4: B 4 2
#> 5: <NA> 5 3
#> 6: <NA> 6 3
#> 7: C 7 4
#> 8: C 8 4
#> 9: C 9 4
#> 10: A 10 5
#> 11: <NA> 11 6
#> 12: B 12 7
#> 13: B 13 7
#> 14: <NA> 14 8
Just for example, Alex's solution is perfect for OP but doesn't give same result as data.table::rleid()
when dealing with NAs
:
# Alex's solution
df %>%
mutate(rleid = (grp != lag(grp, 1, default = "asdf"))) %>%
mutate(rleid = cumsum(rleid))
#> grp value rleid
#> 1 A 1 1
#> 2 A 2 1
#> 3 B 3 2
#> 4 B 4 2
#> 5 <NA> 5 NA
#> 6 <NA> 6 NA
#> 7 C 7 NA
#> 8 C 8 NA
#> 9 C 9 NA
#> 10 A 10 NA
#> 11 <NA> 11 NA
#> 12 B 12 NA
#> 13 B 13 NA
#> 14 <NA> 14 NA
Here is an easy to read and understand tidyverse
(although slower) equivalent to data.table::rleid()
:
# like rleid()
df %>%
mutate(
rleid = cumsum(
ifelse(is.na(grp), "DEFAULT", grp) != lag(ifelse(is.na(grp), "DEFAULT", grp), default = "DEFAULT")
)
)
#> grp value rleid
#> 1 A 1 1
#> 2 A 2 1
#> 3 B 3 2
#> 4 B 4 2
#> 5 <NA> 5 3
#> 6 <NA> 6 3
#> 7 C 7 4
#> 8 C 8 4
#> 9 C 9 4
#> 10 A 10 5
#> 11 <NA> 11 6
#> 12 B 12 7
#> 13 B 13 7
#> 14 <NA> 14 8
Here is an easy to read and understand tidyverse
equivalent to data.table::rleid()
but that ignores NAs
:
# like rleid() but ignoring NAs
df %>%
mutate(
rleid = cumsum(
(!is.na(grp)) & (grp != lag(ifelse(is.na(grp), "DEFAULT", grp), default = "DEFAULT"))
)
)
#> grp value rleid
#> 1 A 1 1
#> 2 A 2 1
#> 3 B 3 2
#> 4 B 4 2
#> 5 <NA> 5 2
#> 6 <NA> 6 2
#> 7 C 7 3
#> 8 C 8 3
#> 9 C 9 3
#> 10 A 10 4
#> 11 <NA> 11 4
#> 12 B 12 5
#> 13 B 13 5
#> 14 <NA> 14 5
Created on 2022-08-27 with reprex v2.0.2