2016-06-30 14 views
5

複数の変数の複数のラグを作成したいので、関数を書くことが役に立ちます。私のコードが警告(「長さ1のベクトルを切捨て」)と、誤った結果スロー:debugging:複数の列(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) 

をもmutate_eachを使用して、よりエレガントな解決策があるかもしれません場合、私は疑問に思いましたが、私はそれはどちらか動作するように取得できませんでした。もちろん、新しい遅れた変数ごとに長いコードを書くこともできますが、Idはそれを避けるのが好きです。

EDIT:

akrunのdplyrの答えは動作しますが、大規模なデータフレームのために計算するのに長い時間がかかります。 data.tableを使用するソリューションがより効率的であるようです。そのため、dplyrや他の解決策では、いくつかの列に実装することも可能です。&いくつかのラグがまだ見つかっています。

EDIT 2:複数の列と、次のソリューションは、そのシンプルさに、私には非常に適しているようだがないグループ(例えば、「ID」)については

。コードはもちろんの短縮が、ステップステップによってすることができる:

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

それは完璧に動作します!私はそれを正しく操作するために 'data.table'を読んでみる必要があります。私のような人は非常に熟練したプログラマーではないと思うのですが、' dplyr'ソリューションは 'dataで更新されました – yoland

+0

です。あなたは 'シフト'をしたい多くの列がある場合のためのテーブルの解決 – akrun

答えて

4

私たちは、「n」を

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

と仮定に対して複数の値を取ることができたdata.tableからshiftを使用することができ、私たちはこれを実行する必要があります複数の列

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はTでも使用することができます彼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

ありがとう、それは動作し、はるかに効率的です!私は今のところ質問を残しておきます – yoland

+0

dplyrコードは新しい列に分かりやすい名前を割り当てる利点がありますが、3列ではなく6列を生成します – yoland

+0

@yolandこれは3列しか与えません。元のデータセットを使用しているのか、 'data.table'を変換したのかを確認してください。 – akrun

関連する問題