使用预测值在 data.table 中进行预测

Using predicted values to make predictions in data.table

我正在尝试解决 data.table 中的一个问题,它要求我在下一步预测中使用刚刚预测的值。

我的数据是这样设置的,生成的 NA 行已准备好接收预测。每个 NA 的计算方法是将其前面的值乘以当前参数

library(data.table)

dt <- data.table(
  date = as.Date(paste(rep(c(2015, 2016), each = 12, times = 2), 1:12, 1, sep = "-")),
  val = c(rnorm(12, 50, 5), rep(NA, 12)),
  param1 = runif(48),
  cat = rep(c("a", "b"), each = 24)
)

我不能这样做

dt[, {
  dt_in <- .SD

  lapply(dt_in[year(date) > 2015, date], function(d){
    dt_sub <- dt_in[date <= d]
    pred <- dt_sub[.N-1, val] * dt_sub[.N, param1]
    dt_in[date == d, val := pred]
  })
} , by = cat]

尝试在 {} 内更新 .SD 时出现“.SD 已锁定...”错误。我当前的解决方案涉及将 data.table 分解为一个列表并逐行更新每个列表项

# Create a list of data.tables, one for each category
break_list <- lapply(dt[, unique(cat)], function(c){
  dt[cat == c]
})

l_out <- lapply(break_list, function(dt_in){
# Select the dates requiring prediction
  lapply(dt_in[year(date) > 2015, date], function(d){
    # Subset by date
    dt_sub <- dt_in[date <= d]
    # Prediciton = value from the second to last row * parameter in the last row
    pred <- dt_sub[.N-1, val] * dt_sub[.N, param1]
    # Update data.table
    dt_in[date == d, val := pred]
  })
  dt_in
})

dt_out <- rbindlist(l_out)

这有效并为我提供了所需的解决方案,但它可能很慢并且感觉我已经违反了所有 data.table 规则。有没有更好的方法?

您正在寻找迭代更新 data.table 的行,其中的值是根据上一次迭代中更新的行计算得出的。虽然通常最好找到使更新独立的问题的明确表述,并且在您的情况下可以使用包含 param1cumprod 的辅助列和滚动连接(dt[dt[...], ..., roll=TRUE]) 我将展示如何使用 data.table::set 有效地对 data.table 进行迭代更新,因为前者并不总是 easy/possible:

setkey(dt, cat, date) # sort by cat first then by date in have the reference value used for each calculation in the row above
val_col_nr <- which(colnames(dt)=="val") # set requires a column number
dt[is.na(val), # we want to compute new values for val where val currently is NA
   # .I is a vector the row numbers (in dt) of each row in .SD
   for (ii in .I) set(dt, i=ii, j=val_col_nr, value=dt[ii,param1]*dt[ii-1L,val]),
   by=cat] # for every 'cat'

您可以使用identical(dt, setkey(dt_out,cat,date))查看结果。

另请注意,使用基本函数的名称(cat 在您的情况下)作为变量名(即使在不同的命名空间中)通常不是一个好主意。