2015-11-03 17 views
10

data.table offre una bella funzione convenienza, rleid:Esiste un dplyr equivalente a 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 

posso imitare questo nella base di 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 

Qualcuno sa di un dplyr equivalente o è il "migliore" modo per creare il comportamento rleid con dplyr è di fare qualcosa di simile al seguente

library(dplyr) 

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

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

Dplyr è compatibile con data.table. Se, per qualche ragione, non vuoi caricare data.table, penso che la tua soluzione di base sia buona. Potresti provare a presentare una richiesta di funzione con dplyr, ma direi che le probabilità di una buona ricezione non sono migliori di 50/50. – Frank

+0

'cumsum (c (1L, df $ grp [-nrow (df)]! = Df $ grp [-1]))' anche per la base – rawr

risposta

16

Si può solo fare (quando si hanno sia data.table e dplyr caricati):

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

questo dà:

> 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 

Quando non si desidera caricare data.table separatamente è anche possibile utilizzare (come detto da @DavidArenburg nei commenti):

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

E come ha detto in @RichardScriven hi s commento si può semplicemente copiare/rubare:

myrleid <- data.table::rleid 
+0

Concordato, ma sto cercando di evitare la chiamata a 'data.table :: rleid' se possibile. – JasonAizkalns

+3

@JasonAizkalns Perché? Se posso chiedere? – Jaap

+0

Per rimanere interamente in 'dplyr',' tidyr', terra hadley-verse. – JasonAizkalns

8

Se si desidera utilizzare solo di base R e dplyr, il modo migliore è quello di concludere la propria versione di uno o due linee di rleid() come funzione e quindi applicalo ogni volta che ne hai bisogno.

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

Piccola nota: 'rleid()' è progettato per funzionare anche con liste/data.frames/data.tables, ad es., 'rleid (c (1,1,1,2,2,2), c (3,4,4,5,5,6))'. Niente di speciale nell'implementarlo, ma solo per notare la differenza. – Arun

+1

@Arun Ah, mi sono perso. Buon punto (e bella funzione). –

+0

@Arun Dovrebbe 'data.table :: rleid (mtcars)' funzionare? (Non lo fa, per quanto mi riguarda, anche se il suo file di aiuto mi porterebbe a credere che dovrebbe ...) –

4

è possibile farlo utilizzando la funzione di lag da dplyr.

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

> 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 
Problemi correlati