我试图解决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已锁定...&#39;错误。我当前的解决方案涉及将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规则。还有更好的方法吗?
答案 0 :(得分:1)
您希望迭代更新data.table的行,并使用从上一次迭代中更新的行计算的值。虽然通常最好找到问题的明确表述,使更新独立,但在您的情况下可以使用包含cumprod
param1
的辅助列和滚动连接({{1}我将展示如何使用dt[dt[...], ..., roll=TRUE]
有效地对data.table进行迭代更新,因为前者并不总是容易/可能:
data.table::set
您可以使用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))
)作为变量名称(即使在不同的名称空间中)通常也是一个坏主意。