在r

时间:2016-07-25 20:52:27

标签: r loops data.table

我试图找到一种更快的解决方案来迭代地定义变量,即变量的下一行取决于前一行。例如,假设我有以下data.table:

tmp <- data.table(type = c("A", "A", "A", "B", "B", "B"), 
                  year = c(2011, 2012, 2013, 2011, 2012, 2013), 
                  alpha = c(1,1,1,2,2,2), 
                  beta = c(3,3,3,4,4,4), 
                  pred = c(1,NA,NA,2,NA, NA))

对于每种类型(A和B),我想解决pre for forward,其中2012年类型A的pred是:

pred_2012_A = alpha + beta * pred_2011_A

并且类型A的2013年预测继续:

pred_2013_A = alpha + beta * pred_2012_A

我有一个解决方案,使用for循环来完成类型并创建一个变量来存储前一个值并使用&#34; by&#34;数据表中的命令循环遍历年份:

for(i in c("A", "B")){
  tmp.val <- tmp[type == i & year == 2011]$pred # initial value for type i
  tmp[year > 2011 & type == i, pred := {
    tmp.val <- alpha + beta * tmp.val
  }, by = year]
}

最终,原始数据表如下所示:

   type year alpha beta pred
1:    A 2011     1    3    1
2:    A 2012     1    3   NA
3:    A 2013     1    3   NA
4:    B 2011     2    4    2
5:    B 2012     2    4   NA
6:    B 2013     2    4   NA

更新后的表格如下:

   type year alpha beta pred
1:    A 2011     1    3    1
2:    A 2012     1    3    4
3:    A 2013     1    3   13
4:    B 2011     2    4    2
5:    B 2012     2    4   10
6:    B 2013     2    4   42

我的问题是,如果没有for循环有更快的方法来实现它。有没有办法在一个比使用for循环更快的数据表语句中实现此例程?我的实际用法有更多类型和更多年的计算时间,因此非常感谢更快的实现。

谢谢。

2 个答案:

答案 0 :(得分:3)

你可以做数学:

tmp[, pred := pred[1]*beta^(1:.N-1) + alpha*cumsum(c(0, beta[1]^(0:(.N-2)))), by=type]

#    type year alpha beta pred
# 1:    A 2011     1    3    1
# 2:    A 2012     1    3    4
# 3:    A 2013     1    3   13
# 4:    B 2011     2    4    2
# 5:    B 2012     2    4   10
# 6:    B 2013     2    4   42

评论。在我看来,OP中的数据结构存在缺陷。 Alpha和beta显然是该类型的属性,而不是从行到行的不同。它应该从:

开始
typeDT = data.table(
  type=c("A","B"), 
  year.start = 2011L, 
  year.end=2013, 
  a = 1:2, 
  b = 3:4,
  pred0 = 1:2
)

#    type year.start year.end a b pred0
# 1:    A       2011     2013 1 3     1
# 2:    B       2011     2013 2 4     2

使用此结构,您可以自然地扩展到您的数据集:

typeDT[, {
  year = year.start:year.end
  n    = length(year)
  p    = pred0*b^(0:(n-1)) + a*cumsum(c(0, b^(0:(n-2))))
  .(year = year, pred = p)
}, by=type]

#    type year pred
# 1:    A 2011    1
# 2:    A 2012    4
# 3:    A 2013   13
# 4:    B 2011    2
# 5:    B 2012   10
# 6:    B 2013   42

答案 1 :(得分:0)

有点hacky但跟我一起,只需要两次迭代。

df <- read.table(text = "type year alpha beta pred
1:    A 2011     1    3    1
2:    A 2012     1    3   NA
3:    A 2013     1    3   NA
4:    B 2011     2    4    2
5:    B 2012     2    4   NA
6:    B 2013     2    4   NA", header = T)

df2 <- df

while(any(is.na(df2$pred))){
  df2$pred <- df2$alpha + df2$beta*lag(df2$pred)
  df2$pred[which(!is.na(df$pred))] <- df$pred[which(!is.na(df$pred))]
}

解决方案是正确的

df2
   type year alpha beta pred
1:    A 2011     1    3    1
2:    A 2012     1    3    4
3:    A 2013     1    3   13
4:    B 2011     2    4    2
5:    B 2012     2    4   10
6:    B 2013     2    4   42