是否可以在仅包含工作日和缺少日期的时间序列数据框中创建引用t-k个工作日的滞后变量?

时间:2019-06-30 20:33:12

标签: r

我有一个时间序列数据帧(请参阅下面的可重现数据帧),我想在t-1和t-2个工作日创建滞后变量值的新列。所有观察均为工作日。数据表根据指定的第一变量/列进行排列,并根据'%Y-%m-%d'格式设置为日期。问题是,有时在数据框中缺少一个或多个工作日的时间间隔,这意味着当我创建滞后变量时,在某些情况下,它可能会导致不正确的滞后值,这些情况是基于以前的观察而实际上NA是由于缺少t-1或t-2工作日而需要指定。因此,我的问题是,是否有任何聪明的方法来创建可避免此问题的滞后变量?

下面我以一个可复制的数据帧为例:

set.seed(1)
Data <- data.frame( date = as.Date(c("2019-06-24", "2019-06-25","2019-06-27", "2019-06-28","2019-07-01", "2019-07-03", "2019-07-04", "2019-07-08", "2019-07-09","2019-07-10")),
  X = sample(1:10),
  Y = sample(1:10),
  Z = sample(c("YES", "NO"), 10, replace = TRUE))

如您所见,我有意省略了一些工作日。而且,如果您运行以下代码来创建传统上滞后变量的代码,则可以观察到输出将不准确。

install.packages(data.table)
library(data.table)
setDT(Data)[, paste0('X', 1:2) := shift(X, 1:2)][]
setDT(Data)[, paste0('Y', 1:2) := shift(Y, 1:2)][]
setDT(Data)[, paste0('Z', 1:2) := shift(Z, 1:2)][]

例如由于缺少日期2019-06-26,在日期2019-06-27上,滞后变量“ X1”和“ X2”的期望输出将为“ NA”。

2 个答案:

答案 0 :(得分:0)

尝试:

library(data.table)

irregularShift <- function(date_var, val, k) sapply(date_var, function(x) val[date_var == x - k])

setDT(Data)[
  , paste0('X', 1:2) := list(irregularShift(date, X, 1), irregularShift(date, X, 2))][
    , paste0('Y', 1:2) := list(irregularShift(date, Y, 1), irregularShift(date, Y, 2))][
      , paste0('Z', 1:2) := list(irregularShift(date, Z, 1), irregularShift(date, Z, 2))
  ]

输出:

          date  X  Y   Z X1 X2 Y1 Y2  Z1  Z2
 1: 2019-06-24  9  3 YES                    
 2: 2019-06-25  4  1 YES  9     3    YES    
 3: 2019-06-27  7  5 YES     4     1     YES
 4: 2019-06-28  1  8  NO  7     5    YES    
 5: 2019-07-01  2  2 YES                    
 6: 2019-07-03  5  6 YES     2     2     YES
 7: 2019-07-04  3 10  NO  5     6    YES    
 8: 2019-07-08 10  9  NO                    
 9: 2019-07-09  6  4  NO 10     9     NO    
10: 2019-07-10  8  7 YES  6 10  4  9  NO  NO

尽管我们正在研究X22019-06-27却没有t-2缺少2019-06-25。如果这是不希望的,则可能需要重新调整您想看到的班次,也许还有其他条件。

答案 1 :(得分:0)

一种解决方案是将缺失的日期添加到数据中,以使shift函数正常工作。在这里,我假设“工作日”指的是工作日,但是显然您可以按任何方式构造向量。这要求您知道哪些天是工作日才能构建向量,但是任何方法都需要知道这一点。

bus_days <- 
  df[, {days <- seq(min(date), max(date), by = 'day')
        days[!format(days, '%u') %in% 6:7]}]

df[J(bus_days), on = 'date']