2017-05-10 36 views
3

背景:
可以說,我有這樣的代碼使用創建滯後列data.table

library(data.table) 

#reproducibility 
set.seed(45L) 

#make table 
dt <- data.table(V1=c(1L,2L), 
       V2=LETTERS[1:3], 
       V3=round(rnorm(4),4), 
       V4 = 1:12) 
dt 

爲此我得到

> dt 
    V1 V2  V3 V4 
1: 1 A 0.3408 1 
2: 2 B -0.7033 2 
3: 1 C -0.3795 3 
4: 2 A -0.7460 4 
5: 1 B 0.3408 5 
6: 2 C -0.7033 6 
7: 1 A -0.3795 7 
8: 2 B -0.7460 8 
9: 1 C 0.3408 9 
10: 2 A -0.7033 10 
11: 1 B -0.3795 11 
12: 2 C -0.7460 12 

,我想創建附加的10列V3的滯後。

問:
是有辦法的「數據表」範例內做到這一點。

更多詳細信息:
如果它是一個data.frame,那麼我可以做一個循環。

dt <- as.data.frame(dt) 


for(i in 1:10){ 
    dt <- cbind(dt, shift(x = dt[, 3], 
          n = i, 
          fill = NA, 
          type = "lag")) 
    names(dt)[ncol(dt)] <- sprintf("lag_%06d",i) 
} 

dt 

爲此,我得到:

> dt 
    V1 V2  V3 V4 lag_000001 lag_000002 lag_000003 lag_000004 lag_000005 lag_000006 lag_000007 lag_000008 lag_000009 lag_000010 
1 1 A 0.3408 1   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA 
2 2 B -0.7033 2  0.3408   NA   NA   NA   NA   NA   NA   NA   NA   NA 
3 1 C -0.3795 3 -0.7033  0.3408   NA   NA   NA   NA   NA   NA   NA   NA 
4 2 A -0.7460 4 -0.3795 -0.7033  0.3408   NA   NA   NA   NA   NA   NA   NA 
5 1 B 0.3408 5 -0.7460 -0.3795 -0.7033  0.3408   NA   NA   NA   NA   NA   NA 
6 2 C -0.7033 6  0.3408 -0.7460 -0.3795 -0.7033  0.3408   NA   NA   NA   NA   NA 
7 1 A -0.3795 7 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408   NA   NA   NA   NA 
8 2 B -0.7460 8 -0.3795 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408   NA   NA   NA 
9 1 C 0.3408 9 -0.7460 -0.3795 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408   NA   NA 
10 2 A -0.7033 10  0.3408 -0.7460 -0.3795 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408   NA 
11 1 B -0.3795 11 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408 
12 2 C -0.7460 12 -0.3795 -0.7033  0.3408 -0.7460 -0.3795 -0.7033  0.3408 -0.7460 -0.3795 -0.7033 

必須有一個更優雅的方式。能夠更快更高效地處理更大數據的東西。

現在如果我想首先做到這一點,在V3列上做10個滯後,然後在V4上做,而不預設他們的名字。我可以簡單地做嵌套for循環,但我懷疑data.table有一些很好的東西(很好?)在那裏提供。

回答

6

是的,shift考慮這種類型的用戶需求。當shift參數n是矢量,shift將在n返回一個列表,每個班次:

dt[, sprintf("V3_lag_%06d", 1:10) := shift(V3, 1:10, type = 'lag')] 
dt[, sprintf("V4_lag_%06d", 1:10) := shift(V4, 1:10, type = 'lag')] 

#  V1 V2  V3 V4 V3_lag_000001 V3_lag_000002 V3_lag_000003 V3_lag_000004 V3_lag_000005 
# 1: 1 A 1.2322 1   NA   NA   NA   NA   NA 
# 2: 2 B 1.6094 2  1.2322   NA   NA   NA   NA 
# 3: 1 C 0.4016 3  1.6094  1.2322   NA   NA   NA 
# 4: 2 A -0.2730 4  0.4016  1.6094  1.2322   NA   NA 
# 5: 1 B 1.2322 5  -0.2730  0.4016  1.6094  1.2322   NA 
# 6: 2 C 1.6094 6  1.2322  -0.2730  0.4016  1.6094  1.2322 
# 7: 1 A 0.4016 7  1.6094  1.2322  -0.2730  0.4016  1.6094 
# 8: 2 B -0.2730 8  0.4016  1.6094  1.2322  -0.2730  0.4016 
# 9: 1 C 1.2322 9  -0.2730  0.4016  1.6094  1.2322  -0.2730 
# 10: 2 A 1.6094 10  1.2322  -0.2730  0.4016  1.6094  1.2322 
# 11: 1 B 0.4016 11  1.6094  1.2322  -0.2730  0.4016  1.6094 
# 12: 2 C -0.2730 12  0.4016  1.6094  1.2322  -0.2730  0.4016 
# V3_lag_000006 V3_lag_000007 V3_lag_000008 V3_lag_000009 V3_lag_000010 V4_lag_000001 
# 1:   NA   NA   NA   NA   NA   NA 
# 2:   NA   NA   NA   NA   NA    1 
# 3:   NA   NA   NA   NA   NA    2 
# 4:   NA   NA   NA   NA   NA    3 
# 5:   NA   NA   NA   NA   NA    4 
# 6:   NA   NA   NA   NA   NA    5 
# 7:  1.2322   NA   NA   NA   NA    6 
# 8:  1.6094  1.2322   NA   NA   NA    7 
# 9:  0.4016  1.6094  1.2322   NA   NA    8 
# 10:  -0.2730  0.4016  1.6094  1.2322   NA    9 
# 11:  1.2322  -0.2730  0.4016  1.6094  1.2322   10 
# 12:  1.6094  1.2322  -0.2730  0.4016  1.6094   11 
# V4_lag_000002 V4_lag_000003 V4_lag_000004 V4_lag_000005 V4_lag_000006 V4_lag_000007 
# 1:   NA   NA   NA   NA   NA   NA 
# 2:   NA   NA   NA   NA   NA   NA 
# 3:    1   NA   NA   NA   NA   NA 
# 4:    2    1   NA   NA   NA   NA 
# 5:    3    2    1   NA   NA   NA 
# 6:    4    3    2    1   NA   NA 
# 7:    5    4    3    2    1   NA 
# 8:    6    5    4    3    2    1 
# 9:    7    6    5    4    3    2 
# 10:    8    7    6    5    4    3 
# 11:    9    8    7    6    5    4 
# 12:   10    9    8    7    6    5 
# V4_lag_000008 V4_lag_000009 V4_lag_000010 
# 1:   NA   NA   NA 
# 2:   NA   NA   NA 
# 3:   NA   NA   NA 
# 4:   NA   NA   NA 
# 5:   NA   NA   NA 
# 6:   NA   NA   NA 
# 7:   NA   NA   NA 
# 8:   NA   NA   NA 
# 9:    1   NA   NA 
# 10:    2    1   NA 
# 11:    3    2    1 
# 12:    4    3    2 
+0

據透露,沒有必要用包'C函數(F())。= ' – Frank

+0

@Frank,我一直以爲我應該在創建多列時使用'c()''data.table'是否首先檢查'LHS'是否是函數? – mt1022

+2

只有一種情況需要'DT [,x:=]'會爲了方便創建一個名爲'x'的列(不需要用引號括起來,比如'「x」:='),但是這意味着如果你想動態定義'x',被包裹在圓括號中,'x =「col」; DT [,(x):=]'。 – Frank

2

它也可以做到這一切在1次data.table通話。

cols <- c("V3","V4") 
dt[, (paste0("lag_",rep(cols, each = 10), "_", rep(1:10, times = length(cols)))) := 
      unlist(lapply(.SD, function(x) shift(x, 1:10, type = "lag")), recursive = F), .SDcols = cols] 

paste0(...)代碼設置了列名,我們想要的方式,然後unlist(lapply(...))代碼獲取滯後於我們想要的順序每列:如果你需要很多的列這可能是特別有用。要了解每個運作的,你可以單獨運行它們(如果運行unlist(lapply(...))你必須在dt[,c("V3","V4")]來替代.SD

dt[,1:9] 
# V1 V2  V3 V4 lag_V3_1 lag_V4_1 lag_V3_2 lag_V4_2 lag_V3_3 
# 1: 1 A 0.3408 1  NA  NA  NA  NA  NA 
# 2: 2 B -0.7033 2 0.3408  1  NA  NA  NA 
# 3: 1 C -0.3795 3 -0.7033  2 0.3408  1  NA 
# 4: 2 A -0.7460 4 -0.3795  3 -0.7033  2 0.3408 
# 5: 1 B 0.3408 5 -0.7460  4 -0.3795  3 -0.7033 
# 6: 2 C -0.7033 6 0.3408  5 -0.7460  4 -0.3795 
# 7: 1 A -0.3795 7 -0.7033  6 0.3408  5 -0.7460 
# 8: 2 B -0.7460 8 -0.3795  7 -0.7033  6 0.3408 
# 9: 1 C 0.3408 9 -0.7460  8 -0.3795  7 -0.7033 
#10: 2 A -0.7033 10 0.3408  9 -0.7460  8 -0.3795 
#11: 1 B -0.3795 11 -0.7033  10 0.3408  9 -0.7460 
#12: 2 C -0.7460 12 -0.3795  11 -0.7033  10 0.3408 
+0

根據我的基準測試,在一次調用中包裝的可讀性較差,但比我的回答稍快。 +1 – mt1022

+1

當然,可讀性較差,我認爲如果他不得不滯後很多不同的列(這樣就不需要很多輸入),這可能會有所幫助。但是,只有幾列,我肯定會選擇你的解決方案 –

+0

我把它封裝在一個循環中。我確實有很多專欄,但是哇。我認爲data.table可能是我新的最好的朋友......從數字上講。 – EngrStudent