2016-06-30 4 views
5

Ich möchte mehrere Verzögerungen von mehreren Variablen erstellen, so dass ich dachte, eine Funktion schreiben wäre hilfreich. Mein Code löst eine Warnung („Kürzen Vektor der Länge 1“) und falsche Ergebnisse:Debugging: Funktion zum Erstellen mehrerer Verzögerungen für mehrere Spalten (dplyr)

library(dplyr) 
time <- c(2000:2009, 2000:2009) 
x <- c(1:10, 10:19) 
id <- c(1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2) 
df <- data.frame(id, time, x) 



three_lags <- function (data, column, group, ordervar) { 
    data <- data %>% 
    group_by_(group) %>% 
    mutate(a = lag(column, 1L, NA, order_by = ordervar), 
      b = lag(column, 2L, NA, order_by = ordervar), 
      c = lag(column, 3L, NA, order_by = ordervar)) 
    } 

df_lags <- three_lags(data=df, column=x, group=id, ordervar=time) %>% 
    arrange(id, time) 

Auch fragte ich mich, ob es vielleicht eine elegantere Lösung mit mutate_each sein, aber ich habe das auch nicht zu arbeiten. Ich kann natürlich nur einen langen Code mit einer Zeile für jede neue verzögerte Variable schreiben, aber ich möchte das vermeiden.

EDIT:

akrun des dplyr Antwort funktioniert, aber dauert eine lange Zeit für großen Datenrahmen zu berechnen. Die Lösung mit data.table scheint effizienter zu sein. So ist ein dplyr oder eine andere Lösung, die auch die für mehrere Spalten implementierte & mehrere Lags erlaubt, noch zu finden.

EDIT 2:

Für mehrere Spalten und keine Gruppen (zum Beispiel „ID“) die folgende Lösung für mich sehr gut geeignet scheint, aufgrund seiner Einfachheit. Der Code kann natürlich verkürzt werden, sondern Schritt für Schritt:

df <- arrange(df, time) 

df.lag <- shift(df[,1:24], n=1:3, give.names = T) ##column indexes of columns to be lagged as "[,startcol:endcol]", "n=1:3" sepcifies the number of lags (lag1, lag2 and lag3 in this case) 

df.result <- bind_cols(df, df.lag) 
+0

Es funktioniert perfekt! Ich muss nur auf 'data.table' nachlesen, um es richtig bearbeiten zu können und für andere gedacht zu sein, die - wie ich - keine sehr fähigen Programmierer sind.' Dplyr' Lösungen sind einfacher zu verstehen – yoland

+0

Ich habe mit den 'Daten aktualisiert. Tabelle "Lösung, wenn es viele Spalten gibt, die Sie die' Verschiebung' machen möchten – akrun

Antwort

4

Wir shift von data.table verwenden können, welche mehrere Werte für ‚n‘ nehmen

library(data.table) 
setDT(df)[order(time), c("a", "b", "c") := shift(x, 1:3) , id][order(id, time)] 

Angenommen, müssen wir dies auf tun mehrere Spalten

df$y <- df$x 
setDT(df)[order(time), paste0(rep(c("x", "y"), each =3), 
       c("a", "b", "c")) :=shift(.SD, 1:3), id, .SDcols = x:y] 

Die shift können auch in t verwendet werden er dplyr

library(dplyr) 
df %>% 
    group_by(id) %>% 
    arrange(id, time) %>% 
    do(data.frame(., setNames(shift(.$x, 1:3), c("a", "b", "c")))) 
# id time  x  a  b  c 
# <dbl> <int> <int> <int> <int> <int> 
#1  1 2000  1 NA NA NA 
#2  1 2001  2  1 NA NA 
#3  1 2002  3  2  1 NA 
#4  1 2003  4  3  2  1 
#5  1 2004  5  4  3  2 
#6  1 2005  6  5  4  3 
#7  1 2006  7  6  5  4 
#8  1 2007  8  7  6  5 
#9  1 2008  9  8  7  6 
#10  1 2009 10  9  8  7 
#11  2 2000 10 NA NA NA 
#12  2 2001 11 10 NA NA 
#13  2 2002 12 11 10 NA 
#14  2 2003 13 12 11 10 
#15  2 2004 14 13 12 11 
#16  2 2005 15 14 13 12 
#17  2 2006 16 15 14 13 
#18  2 2007 17 16 15 14 
#19  2 2008 18 17 16 15 
#20  2 2009 19 18 17 16 
+1

Danke, das funktioniert und ist deutlich effizienter! Ich lasse die Frage für jetzt geöffnet – yoland

+0

Der dplyr-Code produziert 6 Spalten statt 3, obwohl das den sinnvollen Namen den neuen Spalten – yoland

+0

@yoland zuweist Es gibt nur 3 Spalten. Bitte prüfen Sie, ob Sie den ursprünglichen Datensatz oder den nach dem 'data.table' konvertierten Datensatz verwenden. – akrun