2016-06-30 15 views
5

Chcę utworzyć wiele opóźnień wielu zmiennych, więc pomyślałem, że pisanie funkcji byłoby pomocne. Mój kod generuje ostrzeżenie („obcinanie wektor do długości 1”) i fałszywe wyniki:debugowanie: funkcja tworzenia wielokrotnych opóźnień dla wielu kolumn (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) 

Również zastanawiałem się, czy może istnieć bardziej eleganckie rozwiązanie wykorzystujące mutate_each, ale nie dostałem tej pracy albo. Mogę oczywiście napisać długi kod z linią dla każdej zmiennej opóźnionej, ale chciałbym tego uniknąć.

EDIT:

akrun za dplyr odpowiedź działa, ale zajmuje dużo czasu, aby obliczyć dla dużych ramek danych. Rozwiązanie wykorzystujące data.table wydaje się być bardziej wydajne. Tak więc dplyr lub inne rozwiązanie, które również może być zaimplementowane dla kilku kolumn &, wciąż można znaleźć.

EDIT 2:

przypadku wielu kolumn i bez grup (na przykład „id”) następujące rozwiązanie wydaje się bardzo dobrze nadaje się do mi, ze względu na jego prostotę. Kod może oczywiście ulec skróceniu, ale krok po kroku:

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

Działa doskonale! Muszę tylko przeczytać na "data.table", aby móc poprawnie nim manipulować i pomyśleć o innych, którzy - jak ja - nie są bardzo wprawnymi programistami, rozwiązania 'dplyr' są łatwiejsze w zrozumieniu. – yoland

+0

Zaktualizowałem za pomocą' danych. rozwiązanie tabeli w przypadku, gdy istnieje wiele kolumn, które chcesz zrobić 'shift' – akrun

Odpowiedz

4

Możemy wykorzystać shift z data.table który może trwać wiele wartości dla „n”

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

Załóżmy, musimy to zrobić na wiele kolumn

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] 

shift może być również stosowany w t on 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

Dziękuję, że działa i jest wyraźnie bardziej wydajny! Pozostawiam pytanie otwarte na teraz – yoland

+0

Kod dplyr tworzy 6 kolumn zamiast 3, mimo że ma tę zaletę, że przypisuje sensowne nazwy do nowych kolumn – yoland

+0

@yoland Daje tylko 3 kolumny. Sprawdź, czy korzystasz z oryginalnego zestawu danych, czy też po konwersji danych "data.table". – akrun

Powiązane problemy