【问题标题】:Define variable iteratively in data table in r在r中的数据表中迭代地定义变量
【发布时间】:2016-07-25 20:52:26
【问题描述】:

我正在尝试找到一种更快的解决方案来迭代定义变量,即变量的下一行取决于前一行。例如,假设我有以下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),我想解决 pred 的问题,其中 2012 年类型 A 的 pred 是:

pred_2012_A = alpha + beta * pred_2011_A

2013 年 A 型的预测仍在继续:

pred_2013_A = alpha + beta * pred_2012_A

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

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 循环更快?我的实际使用需要计算更多类型和更多年,因此将不胜感激更快的实现。

谢谢。

【问题讨论】:

  • 感谢您的解决方案,弗兰克。但是,似乎我把这个例子做得太简单了。如果预测值没有基于初始值的良好封闭形式解决方案怎么办?最终,我试图看看在计算 pred 的下一个值时访问 pred 的前一个值的最快方法是什么,而不是将其存储在临时变量中并使用 for 循环。我认为如果 alpha 和 beta 每年都在变化,情况可能就是这样。这有意义吗?
  • 如果您的解决方案必须是迭代的,那么除了循环之外,没有办法(我猜是用 R 或任何语言)。这样的 for 循环在 R 中可能会很慢,但您可以将其转换为 C++ 并使用 Rcpp 库,这可能会有很大帮助。

标签: r loops data.table


【解决方案1】:

你可以算一下:

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

【讨论】:

    【解决方案2】:

    有点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
    

    【讨论】:

    • 我很困惑。如果不考虑按type 分组,它是如何工作的?
    • ...因为他对每种类型都有第一个 pred 值。不确定这是一个公平的假设,然后,正如您所指出的,这个问题并不完全适合这个例子。这并不是最糟糕的假设,因为如果没有第一个值,您就不得不执行一堆 NA。
    • 好的。我怀疑这也取决于每组的行数相同,但还没有真正考虑过。
    猜你喜欢
    • 2015-10-26
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 2021-11-01
    相关资源
    最近更新 更多