2016-07-25 64 views
1

我想找到更快的解决方案来迭代地定义变量,即变量的下一行取决于前一行。例如,假设我有以下data.table:在r中的数据表中迭代地定义变量

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),我要解决的预解码向前发展,其中预解码A型2012年是:

pred_2012_A = alpha + beta * pred_2011_A 

和预解码2013年A型继续:

pred_2013_A = alpha + beta * pred_2012_A 

我使用for循环要经历类型,并创建一个变量来存储以前的值,并使用“通过”的解决方案命令在数据表中遍历年为这样:

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循环更快的数据表语句中实现此例程?我真正的用法有更多的类型和更多的年份来计算,所以更快的实现将不胜感激。

谢谢。

+0

谢谢您的解决方案弗兰克。但是,我似乎让这个例子太简单了。如果预测值根据初始值没有一个很好的封闭形式解决方案会怎样?最终,我试图看看在计算pred的下一个值时访问pred的前一个值的最快方法,而不将其存储在临时变量中并使用for循环。我认为这可能是这种情况,如果alpha和beta每年都会发生变化。这有意义吗? – naveendaftari

+0

如果你的解决方案必须迭代,除了循环之外,没有办法(在R或任何语言中,我猜)。这样的for循环在R中可能会很慢,但是可以将它翻译成C++并使用Rcpp库,这可能会有很大的帮助。 – Frank

回答

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 
0

有点哈克但忍耐一下,只需要两次迭代。

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 
+1

我很困惑。如何在没有使用'type'进行分组的情况下工作? – Frank

+0

...因为他拥有每种类型的第一个预估值。不确定这是否是一个合理的假设,然后再次,这个问题并不完全适合这个例子,正如你所指出的那样。这并不是最糟糕的假设,因为如果没有第一个价值,你会诉诸大量新秀。 – shayaa

+0

好的。我怀疑这也取决于每组的行数相同,但并没有真正想到它。 – Frank