r dplyr data.table run-length-encoding

¿Hay un dplyr equivalente a data.table:: rleid?



run-length-encoding (4)

data.table ofrece una buena función de conveniencia, rleid para la codificación de longitud de ejecución:

library(data.table) DT = data.table(grp=rep(c("A", "B", "C", "A", "B"), c(2, 2, 3, 1, 2)), value=1:10) rleid(DT$grp) # [1] 1 1 2 2 3 3 3 4 5 5

Puedo imitar esto en la base R con:

df <- data.frame(DT) rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths) # [1] 1 1 2 2 3 3 3 4 5 5

¿Alguien sabe de un equivalente dplyr (?) O es la "mejor" forma de crear el comportamiento dplyr con dplyr es hacer algo como lo siguiente

library(dplyr) my_rleid = rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths) df %>% mutate(rleid = my_rleid)


Puede hacerlo utilizando la función de lag de dplyr .

DT <- DT %>% mutate(rleid = (grp != lag(grp, 1, default = "asdf"))) %>% mutate(rleid = cumsum(rleid))

da

> DT grp value rleid 1: A 1 1 2: A 2 1 3: B 3 2 4: B 4 2 5: C 5 3 6: C 6 3 7: C 7 3 8: A 8 4 9: B 9 5 10: B 10 5


Si desea usar solo base R y dplyr , la mejor manera es envolver su propia versión de una o dos líneas de rleid() como una función y luego aplicarla siempre que la necesite.

library(dplyr) myrleid <- function(x) { x <- rle(x)$lengths rep(seq_along(x), times=x) } ## Try it out DT <- DT %>% mutate(rlid = myrleid(grp)) DT # grp value rlid # 1: A 1 1 # 2: A 2 1 # 3: B 3 2 # 4: B 4 2 # 5: C 5 3 # 6: C 6 3 # 7: C 7 3 # 8: A 8 4 # 9: B 9 5 #10: B 10 5


Simplemente puede hacer (cuando tiene tanto data.table como dplyr cargados):

DT <- DT %>% mutate(rlid = rleid(grp))

esto da:

> DT grp value rlid 1: A 1 1 2: A 2 1 3: B 3 2 4: B 4 2 5: C 5 3 6: C 6 3 7: C 7 3 8: A 8 4 9: B 9 5 10: B 10 5

Cuando no desee cargar data.table separado, también puede usar (como lo menciona @DavidArenburg en los comentarios):

DT <- DT %>% mutate(rlid = data.table::rleid(grp))

Y como dijo @RichardScriven en su comentario, puedes copiarlo / robarlo:

myrleid <- data.table::rleid


Una simplificación (que no implica un paquete adicional) del enfoque utilizado por el OP podría ser:

DT %>% mutate(rleid = with(rle(grp), rep(seq_along(lengths), lengths))) grp value rleid 1 A 1 1 2 A 2 1 3 B 3 2 4 B 4 2 5 C 5 3 6 C 6 3 7 C 7 3 8 A 8 4 9 B 9 5 10 B 10 5

O:

DT %>% mutate(rleid = rep(seq(ls <- rle(grp)$lengths), ls))