2016-05-10 26 views
2

我想轉置一個時間序列數據集以提供給某些機器學習算法。下面是想我做的,除了滯後的數量的例子大,我在尋找一個更優雅的方式來做到這一點:使用dplyr轉置時間序列(帶有滯後的變異)

set.seed(42) 
data <- data.frame(time = 1:5, value = rnorm(5)) 
data 
# time  value 
# 1 1 1.3709584 
# 2 2 -0.5646982 
# 3 3 0.3631284 
# 4 4 0.6328626 
# 5 5 0.4042683 
data %>% 
    mutate(lag_1 = lag(value), 
     lag_2 = lag(value, 2), 
     lag_3 = lag(value, 3), 
     lag_4 = lag(value, 4), 
     lag_5 = lag(value, 5)) 
# time  value  lag_1  lag_2  lag_3 lag_4 lag_5 
# 1 1 1.3709584   NA   NA   NA  NA NA 
# 2 2 -0.5646982 1.3709584   NA   NA  NA NA 
# 3 3 0.3631284 -0.5646982 1.3709584   NA  NA NA 
# 4 4 0.6328626 0.3631284 -0.5646982 1.3709584  NA NA 
# 5 5 0.4042683 0.6328626 0.3631284 -0.5646982 1.370958 NA 

回答

4

您可以將使用data.table更方便,因爲從shiftdata.table允許參數n是一個向量,而dplyr中的lag函數不會。

library(data.table) 
> setDT(data)[, paste("lag", 1:5, sep = "_") := shift(value, 1:5)] 
> data 
    time  value  lag_1  lag_2  lag_3  lag_4 lag_5 
1: 1 -1.4162466   NA   NA   NA  NA NA 
2: 2 -0.2366333 -1.4162466   NA   NA  NA NA 
3: 3 0.5146632 -0.2366333 -1.4162466   NA  NA NA 
4: 4 1.9243923 0.5146632 -0.2366333 -1.4162466  NA NA 
5: 5 1.6161165 1.9243923 0.5146632 -0.2366333 -1.416247 NA 

更具體有關shiftlag,這裏是如何的lag功能不會讓你做什麼shift做一個例子。

> vec <- 1:10 
> shift(vec, 1:2) 
[[1]] 
[1] NA 1 2 3 4 5 6 7 8 9 

[[2]] 
[1] NA NA 1 2 3 4 5 6 7 8 

> lag(vec, 1:2) 
Error in lag(vec, 1:2) : n must be a single positive integer 
In addition: Warning message: 
In if (n == 0) return(x) : 
    the condition has length > 1 and only the first element will be used 
1

bind_cols可能比mutate更方便,因爲它很容易產生滯後的data.frame,要麼向量化版本的dplyr::lagdata.table::shift

data %>% bind_cols(setNames(data.frame(Vectorize(lag, 'n')(.$value, 1:5)), 
          paste0('lag_', 1:5))) 
# Source: local data frame [5 x 7] 
# 
# time  value  lag_1  lag_2  lag_3 lag_4 lag_5 
# (int)  (dbl)  (dbl)  (dbl)  (dbl) (dbl) (dbl) 
# 1  1 1.3709584   NA   NA   NA  NA NA 
# 2  2 -0.5646982 1.3709584   NA   NA  NA NA 
# 3  3 0.3631284 -0.5646982 1.3709584   NA  NA NA 
# 4  4 0.6328626 0.3631284 -0.5646982 1.3709584  NA NA 
# 5  5 0.4042683 0.6328626 0.3631284 -0.5646982 1.370958 NA 

data %>% bind_cols(data.frame(shift(.$value, 1:5, give.names = TRUE))) 
# Source: local data frame [5 x 7] 
# 
# time  value V1_lag_1 V1_lag_2 V1_lag_3 V1_lag_4 V1_lag_5 
# (int)  (dbl)  (dbl)  (dbl)  (dbl) (dbl) (dbl) 
# 1  1 1.3709584   NA   NA   NA  NA  NA 
# 2  2 -0.5646982 1.3709584   NA   NA  NA  NA 
# 3  3 0.3631284 -0.5646982 1.3709584   NA  NA  NA 
# 4  4 0.6328626 0.3631284 -0.5646982 1.3709584  NA  NA 
# 5  5 0.4042683 0.6328626 0.3631284 -0.5646982 1.370958  NA 

或者,您也可以使用純老data.frame代替:

data.frame(data, shift(data$value, 1:5, give.names = TRUE)) 
+0

我認爲這是最接近精神(沒有使用引用語義)我正在尋找...有沒有辦法推廣到「分組變異」,其中滯後取決於分組? – kevinykuo

+0

這聽起來像是另一個問題,沒有一個例子就不是很清楚。如果我正確地理解了你,你可以滯後組,但是'滯後'不能真正計算第二個參數中的任何東西(即使'2-1'失敗)。 'shift'稍微好一點,但仍然不能處理'n()',這很有用,但你可能會使整個事情在純data.table中工作。 – alistaire

0

這可以用base R由USI做ng lapply。我們使用lapply循環訪問k,並將輸出分配給「數據」中的新列。

data[paste("lag", 1:5, sep="_")] <- lapply(1:5, function(i) lag(data$value, i)) 
data 
# time  value  lag_1  lag_2  lag_3 lag_4 lag_5 
#1 1 1.3709584   NA   NA   NA  NA NA 
#2 2 -0.5646982 1.3709584   NA   NA  NA NA 
#3 3 0.3631284 -0.5646982 1.3709584   NA  NA NA 
#4 4 0.6328626 0.3631284 -0.5646982 1.3709584  NA NA 
#5 5 0.4042683 0.6328626 0.3631284 -0.5646982 1.370958 NA