2013-02-13 14 views
22

Questa è una mia df (data.frame):Calcolare differenza tra i valori in righe consecutive dal gruppo

group value 
[1] 1  10 
[2] 1  20 
[3] 1  25 
[4] 2  5 
[5] 2  10 
[6] 2  15 
    ... 

ho bisogno di calcolare differenza tra i valori in righe consecutive per gruppo.

Quindi, ho bisogno di un risultato.

group value diff 
[1] 1  10 NA (because there is a no previous value) 
[2] 1  20 10 (value[2]-value[1]) 
[3] 1  25 5 (value[3]-value[2]) 
[4] 2  5  NA (because group is changed) 
[5] 2  10 5 (value[5]-value[4]) 
[6] 2  15 5 (value[6]-value[5]) 
    ... 

Anche se, posso gestire questo problema utilizzando ddply, ma ci vuole troppo tempo. Questo perché ho un sacco di gruppi nel mio df. (Oltre 1.000.000 di gruppi nella mia df)

Ci sono altri approcci efficaci per gestire questo problema?

risposta

29

Il pacchetto data.table può fare questo abbastanza rapidamente.

require(data.table) 
df <- data.table(group = rep(c(1, 2), each = 3), value = c(10,20,25,5,10,15)) 
#setDT(df) #if df is already a data frame 
setkey(df, group) 
df[ , diff := c(NA, diff(value)), by = group]  
# group value diff 
#1:  1 10 NA 
#2:  1 20 10 
#3:  1 25 5 
#4:  2  5 NA 
#5:  2 10 5 
#6:  2 15 5 
setDF(df) #if you want to convert back to old data.frame syntax 

o utilizzando dplyr

library(dplyr) 
df %>% 
    group_by(group) %>% 
    mutate(Diff = c(NA, diff(value))) 
+1

Qualche possibilità si conosce una soluzione ddply? Avevo lavorato a questo per un po 'prima che ragionassi che avrebbe potuto necessitare di una funzione diversa. . . –

+2

Suppongo che si tratti di qualcosa come 'ddply (df,. (Gruppo), transform, diff = c (NA, diff (valore)))' –

+0

come si può modificare questo per calcolare la variazione percentuale? –

4

provare questo con Tapply

df$diff<-as.vector(unlist(tapply(df$value,df$group,FUN=function(x){ return (c(NA,diff(x)))}))) 
+3

questo è quello che dovevo fare: 'df $ diff <- unlist (tapply (df $ valore, df $ gruppo, funzione (x) c (NA, diff (x))))' –

12

È possibile utilizzare la funzione di base ave() per questo

df <- data.frame(group=rep(c(1,2),each=3),value=c(10,20,25,5,10,15)) 
df$diff <- ave(df$value, factor(df$group), FUN=function(x) c(NA,diff(x))) 

che restituisce

group value diff 
1  1 10 NA 
2  1 20 10 
3  1 25 5 
4  2  5 NA 
5  2 10 5 
6  2 15 5 
+0

Domanda relativa: http://stackoverflow.com/questions/30378946/calculating-time-difference-by-id Ho trovato entrambi i thread utili. Per le date, puoi usare questo: 'df $ diff <- ave (as.numeric (df $ Datevalue), factor (df $ group), FUN = function (x) c (NA, diff (x)))' , puoi cambiare la posizione del NA se vuoi che l'ultima riga del gruppo abbia l'NA. 'df $ diff <- ave (as.numeric (df $ Datevalue), factor (df $ group), FUN = function (x) c (diff (x), NA))' –

Problemi correlati