累积值:for循环到Reduce

时间:2014-09-17 20:19:11

标签: r

我有一个非常简单的for循环添加可变速率复合兴趣。我试图用矢量化的方式来做,也许使用Reduce这是有意义的(我认为它不是真正的矢量化)。但尝试未能产生相同的结果:

principal <- 10000
rates <- c(0.03, 0.04, 0.05, 0.03, 0.04, 0.05)
balance <- rep(NA, length(rates) + 1)
balance[1] <- principal

for (i in seq_along(rates)){
    balance[i + 1] <- balance[i] * (1 + rates[i]) 
}

## > balance
## [1] 10000.00 10300.00 10712.00 11247.60 11585.03 12048.43 12650.85

以下是Reduce尝试:

growth <- function(balance, rate) {
    balance * (1 + rate)    
}

Reduce(growth, principal, rates, accumulate = TRUE)

但是这给了:

## [[1]]
## [1] 0.03 0.04 0.05 0.03 0.04 0.05
## 
## [[2]]
## [1] 300.03 400.04 500.05 300.03 400.04 500.05

这是预期的,因为我无法将Reduce的向量作为rates提供。我想要的是ReduceMap之间的组合。也许for循环是最好的方法。但是有没有办法吗?

3 个答案:

答案 0 :(得分:5)

也许你的例子太简单了。这样就够了吗?

principal <- 10000
rates <- c(0, 0.03, 0.04, 0.05, 0.03, 0.04, 0.05)
principal*cumprod(1+rates)
## [1] 10000.00 10300.00 10712.00 11247.60 11585.03 12048.43 12650.85

答案 1 :(得分:5)

我认为你没有正确使用Reduce,它应该是:

Reduce(growth, rates, init = principal, accumulate = TRUE)
# [1] 10000.00 10300.00 10712.00 11247.60 11585.03 12048.43 12650.85

答案 2 :(得分:1)

因为你关心速度/矢量化。

WHILE <- function(rate = c(3,4,5,3,4,5), tuit = c(10000, rep(NA,6))){
    i <- 1
    while (i < length(tuit) ) {
      tuit[i+1]  =  tuit[i]*(1+ (rate[i]/100) )
      i = i + 1
    }
    tuit
}

FOR <- function(principle=10000, rates=c(0.03, 0.04, 0.05, 0.03, 0.04, 0.05)){
    balance <- rep(NA, length(rates) + 1)
    balance[1] <- principle

    for (i in seq_along(rates)){
        balance[i + 1] <- balance[i] * (1 + rates[i]) 
    }
    balance
}


REDUCE <- function(principal=10000, rates=c(0.03, 0.04, 0.05, 0.03, 0.04, 0.05)){
    growth <- function(balance, rate) {
        balance * (1 + rate)    
    }

    Reduce(growth, rates, init = principal, accumulate = TRUE)
}

VECTORIZED <- function(principal=10000, rates=c(0.03, 0.04, 0.05, 0.03, 0.04, 0.05)){
    principal*cumprod(1+rates)
}

(op <- microbenchmark::microbenchmark( 
    WHILE(),
    FOR(),
    REDUCE(),
    VECTORIZED(),
times=1000L))

enter image description here

enter image description here