2015-11-03 21 views
10

data.table oferuje ładne funkcji wygodę, rleid:Czy istnieje odpowiednik dplyr dla data.table :: rleid?

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 

mogę naśladować ten w bazie R z: (?)

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 

Czy ktoś wie o dplyr równoważne lub jest "najlepszy" sposób, aby utworzyć zachowanie rleid z dplyr jest zrobić coś jak następuje

library(dplyr) 

my_rleid = rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths) 

df %>% 
    mutate(rleid = my_rleid) 
+7

Dplyr jest kompatybilny z data.table. Jeśli, z jakiegoś powodu, nie chcesz ładować data.table, myślę, że twoje podstawowe rozwiązanie jest dobre. Możesz spróbować zgłosić żądanie funkcji dplyr, ale powiedziałbym, że szanse na dobry odbiór nie są lepsze niż 50/50. – Frank

+0

'cumsum (c (1L, df $ grp [-nrow (df)]! = Df $ grp [-1]))' również dla bazy – rawr

Odpowiedz

16

Można po prostu zrobić (jeśli masz zarówno data.table i dplyr załadowanego):

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

to daje:

> 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 

Jeżeli nie chcesz, aby załadować data.table osobno można również użyć (jak wspomniano przez @DavidArenburg w komentarzach):

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

I jako @RichardScriven powiedział w cześć s skomentować można po prostu skopiować/ukraść go:

myrleid <- data.table::rleid 
+0

Zgadzam się, ale staram się unikać wywołania 'data.table :: rleid' jeśli to możliwe. – JasonAizkalns

+3

@JasonAizkalns Dlaczego? Jeśli mogę zapytać? – Jaap

+0

Pozostawać całkowicie w 'dplyr',' tidyr', werset-werset. – JasonAizkalns

8

Jeśli chcesz używać tylko zasady R i dplyr, lepszym sposobem jest zakończyć swoją własną wersję jednego lub dwóch linii rleid() jako funkcję i następnie stosuj to, kiedy tylko tego potrzebujesz.

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 
+6

Mała uwaga: 'rleid()' jest również przeznaczony do pracy z listami/data.frames/data.tables, np., "rleid (c (1,1,1,2,2,2), c (3,4,4,5,5,6))". Nic specjalnego w jego implementacji, ale tylko zauważenie różnicy. – Arun

+1

@Arun Ah, tęskniłem za tym. Dobry punkt (i fajna funkcja). –

+0

@Arun Czy plik 'data.table :: rleid (mtcars)' działa? (Nie dla mnie, chociaż jego plik pomocy mógłby mnie przekonać, że powinien ...) –

4

Można to zrobić za pomocą funkcji lag z dplyr.

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

daje

> 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 
Powiązane problemy