2017-05-03 2 views
1

mimick Um Daten im Laufe der Zeit zu manipulieren/summieren, verwende ich normalerweise SQL ROW_NUMBER() OVER (PARTITION von ...). Ich bin neu in R, also versuche ich Tabellen neu zu erstellen, die ich sonst in SQL erstellen würde. Das Paket sqldf erlaubt keine OVER-Klauseln. Beispieltabelle:Wie man ROW_NUMBER() OVER (...) in R

ID Day Person Cost 
1  1  A  50  
2  1  B  25  
3  2  A  30  
4  3  B  75  
5  4  A  35  
6  4  B  100  
7  6  B  65  
8  7  A  20  

ich meine letzte Tabelle den Durchschnitt der vorangegangenen zwei Instanzen für jeden Tag nach der zweiten Instanz (Tag 4 für beide) enthalten sein sollen:

ID Day Person Cost  Prev2 
5  4  A  35  40 
6  4  B  100 50 
7  6  B  65  90 
8  7  A  20  35 

Ich habe versucht, um mit aggregate herumzuspielen, aber ich bin nicht wirklich sicher, wie man die Funktion teilt oder qualifiziert. Idealerweise würde ich es vorziehen, nicht die Tatsache zu verwenden, dass id sequenziell mit dem Datum ist, um meine Antwort zu bilden (d. H. Die ursprüngliche Tabelle könnte mit zufälliger Datumsreihenfolge neu angeordnet werden und Code würde immer noch funktionieren). Lassen Sie mich wissen, wenn Sie weitere Informationen benötigen, vielen Dank für Ihre Hilfe!

+0

Sie können OVER mit sqldf verwenden, wenn Sie das PostgreSQL-Backend verwenden. –

Antwort

0

Sie zoo::rollapplyr mit einer Breite von 2. In dplyr hinken konnte

library(dplyr) 

df %>% arrange(Day) %>% # sort 
    group_by(Person) %>% # set grouping 
    mutate(Prev2 = lag(zoo::rollapplyr(Cost, width = 2, FUN = mean, fill = NA))) 
#> Source: local data frame [8 x 5] 
#> Groups: Person [2] 
#> 
#>  ID Day Person Cost Prev2 
#> <int> <int> <fctr> <int> <dbl> 
#> 1  1  1  A 50 NA 
#> 2  2  1  B 25 NA 
#> 3  3  2  A 30 NA 
#> 4  4  3  B 75 NA 
#> 5  5  4  A 35 40.0 
#> 6  6  4  B 100 50.0 
#> 7  7  6  B 65 87.5 
#> 8  8  7  A 20 32.5 

oder alle in dplyr,

df %>% arrange(Day) %>% group_by(Person) %>% mutate(Prev2 = (lag(Cost) + lag(Cost, 2))/2) 

, die die gleiche Sache zurückgibt. In Basis,

df <- df[order(df$Day), ] 

df$Prev2 <- ave(df$Cost, df$Person, FUN = function(x){ 
    c(NA, zoo::rollapplyr(x, width = 2, FUN = mean, fill = NA)[-length(x)]) 
}) 

df 
#> ID Day Person Cost Prev2 
#> 1 1 1  A 50 NA 
#> 2 2 1  B 25 NA 
#> 3 3 2  A 30 NA 
#> 4 4 3  B 75 NA 
#> 5 5 4  A 35 40.0 
#> 6 6 4  B 100 50.0 
#> 7 7 6  B 65 87.5 
#> 8 8 7  A 20 32.5 

oder ohne Zoo,

df$Prev2 <- ave(df$Cost, df$Person, FUN = function(x){ 
    (c(NA, x[-length(x)]) + c(NA, NA, x[-(length(x) - 1):-length(x)]))/2 
}) 

, die das Gleiche tut. Wenn Sie die NA Reihen entfernen möchten, kleben Sie auf tidyr::drop_na(Prev2) oder na.omit.

+0

Danke für die Antwort! Ich habe dplyr in verschiedenen Tutorials verwendet, aber ich habe es nie wirklich für mein eigenes "Projekt" benutzt. Zeit zum Eintauchen – CoolGuyHasChillDay