简化循环计算

时间:2013-10-17 19:08:37

标签: r loops

考虑以下向量 x

 > 1:9
 [1] 1 2 3 4 5 6 7 8 9

并考虑以下输入:

 start = 10
 pmt = 2

这是结果(让我们调用结果向量res)我希望实现(显示的是实际的公式)。请注意,结果是向量而不是数据帧。我只是在这里展示了2个维度。

enter image description here

换句话说,要获得 res ,您需要为start的每个单元格的累积产品多达df到相应的单元格。

当矢量索引是倍数是4或7时,起始值会更新。

这就是我的尝试:

     for(i in 1:9) {
         res[i] = start * cumprod(df[k:i])[i]
         if(i %% 3 == 0) {
             start = res[i] - pmt
             k = k + 3
         } else {
             start = res[i]
         }
     }
 }

要将问题置于上下文中,假设您的初始值为10美元,并且您希望将其投资超过9个月。但是,您希望在每3个月结束时(即第4个月,第7个月......)开始提款。向量 x 表示返回的随机值。 因此,在第4个月的开头,您的初始值为start*1*2*3 减去提款pmt

这里的目的是计算9月底的财富价值。

问题在于,实际上,i = 200(200个月),我需要为10,000个不同的向量 x 重做此计算。因此,在上面的代码上循环10,000次需要永远执行!

您对如何更有效地计算这一点有什么建议吗?我希望解释不要太混乱!

谢谢!

2 个答案:

答案 0 :(得分:3)

如果您将res的公式计算为迭代公式,那么编写一个可以赋予Reduce的函数会更容易。这是一个简单的循环

x <- 1:9
start <- 10
pmt <- 2

res <- numeric(length(x))
res[1] <- x[1] * start
for (i in seq_along(x)[-1]) {
  res[i] <- (res[i-1] - (pmt * (!(i%%4) || !(i%%7)))) * x[i]
}

如果你想把它写成Reduce函数,它看起来像这样

Reduce(function(r, i) {
  (r - (pmt * (!(i%%4) || !(i%%7)))) * x[i]
}, 
       seq_along(x),
       init = start, 
       accumulate = TRUE)[-1]

由于处理初始值的方式(并且迭代是通过索引而不是值,因为必须对索引进行比较),启动值和删除结果的第一个元素有一些奇怪之处。这里的循环可能更容易理解。

答案 1 :(得分:0)

我知道你提到它是1d,但我认为这很有效,你可以很容易地将它转换为1d -

start = 10
pmt = 2

library(data.table)

dt <- data.table(
month = 1:13
)

dt[,principalgrown := start*cumprod(month)]

#explained below#######
dt[,interestlost := 0]
for(i in seq(from = 4, to = (dim(dt)[1]), by = 3))
{
dt[month >= i,interestlost := interestlost + (prod(i:month)), by = month]
}
#######################

dt[,finalamount := principalgrown - (pmt*interestlost)]

#s中的部分就是诀窍。如果您将第7个月的值计算为((1*2*3*start - pmt)*4*5*6 - pmt) * 7,我会将其计算为1*2*3*4*5*6*7*start - 4*5*6*7*pmt - 7*pmt1*2*3*4*5*6*7*startprincipalgrown- 4*5*6*7*pmt - 7*pmt-(pmt*interestlost)