考虑以下向量 x :
> 1:9
[1] 1 2 3 4 5 6 7 8 9
并考虑以下输入:
start = 10
pmt = 2
这是结果(让我们调用结果向量res
)我希望实现(显示的是实际的公式)。请注意,结果是向量而不是数据帧。我只是在这里展示了2个维度。
换句话说,要获得 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次需要永远执行!
您对如何更有效地计算这一点有什么建议吗?我希望解释不要太混乱!
谢谢!
答案 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*pmt
。 1*2*3*4*5*6*7*start
为principalgrown
,- 4*5*6*7*pmt - 7*pmt
为-(pmt*interestlost)