Calcolare la differenza tra i valori di righe consecutive dal gruppo

Questo è un mio df (i dati.frame):

group value
1     10
1     20
1     25
2     5
2     10
2     15 

Ho bisogno di calcolare la differenza tra i valori di righe consecutive dal gruppo.

Così, ho bisogno di un tale risultato.

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

Anche se, sono in grado di gestire questo problema utilizzando ddply, ma ci vuole troppo tempo. Questo è perché ho un sacco di gruppi nella mia df. (oltre 1.000.000 di gruppi nella mia df)

Ci sono altri metodi efficaci per gestire questo problema?

InformationsquelleAutor kmangyo | 2013-02-13

 

3 Replies
  1. 78

    Il pacchetto data.table abbastanza rapidamente, utilizzando il shift funzione.

    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
    
    df[ , diff := value - shift(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 il lag funzione in dplyr

    df %>%
        group_by(group) %>%
        mutate(Diff = value - lag(value))
    #   group value  Diff
    #   <int> <int> <int>
    # 1     1    10    NA
    # 2     1    20    10
    # 3     1    25     5
    # 4     2     5    NA
    # 5     2    10     5
    # 6     2    15     5

    Alternative pre-data.table::shift e pre-dplyr::lag, vedere le modifiche.

    • Qualche possibilità che tu conosca un ddply soluzione? Ho lavorato a questo per un po ‘ prima ho pensato che potrebbe aver bisogno di una funzione diversa. . .
    • Presumo che sarebbe qualcosa di simile a ddply(df, .(group), transform, diff=c(NA,diff(value)))
    • come è possibile modificare questo per calcolare la variazione percentuale?
    • Si potrebbe applicare a qualsiasi funzione qui. Per esempio, se questa è la nostra funzione: perc_change <- function(x, y) { return(x/y*100) }, quindi si potrebbe chiamare come df[ , perc_diff := perc_change(value, shift(value)), by = group]
    • Come si può sostituire il NA per il valore successivo, in modo Diff per la riga 1 sarà anche 10 come per la riga 2?
  2. 19

    È 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
    • Domanda correlata: stackoverflow.com/questions/30378946/… ho trovato entrambi i thread di essere utile. Per le date, è possibile utilizzare questo: df$diff <- ave(as.numeric(df$Datevalue), factor(df$group), FUN=function(x) c(NA,diff(x))) Inoltre, è possibile cambiare la posizione della NA, se si desidera che l’ultima riga del gruppo NA, invece. df$diff <- ave(as.numeric(df$Datevalue), factor(df$group), FUN=function(x) c(diff(x), NA))
  3. 4

    provare questo con tapply

    df$diff<-as.vector(unlist(tapply(df$value,df$group,FUN=function(x){ return (c(NA,diff(x)))})))
    • questo è quello che ho dovuto fare: df$diff <- unlist(tapply(df$value,df$group, function(x) c(NA,diff(x))))

Lascia un commento