R中的滚动计算

时间:2015-01-23 09:28:52

标签: r data.table

我正在尝试使用数据表对R中的摊销贷款帐户进行建模。每行代表一个月。每个月都有还款或预付款,以及基于前一个月余额的利息费用。

例如:

> loan <- data.table(loan.age = seq(0:9), payment = c(5000, -rep(100,9)))

我无法看到添加兴趣和平衡列的简单方法。对于每月1%的利率,利息应该是前一个月余额的0.01倍,新余额应该是上个月的余额加上当月的利息加上当月的付款(通常为负数)。在伪代码中:

this_balance = last_balance + last_balance * 0.01 + this_payment

这是我正在寻找的结果:

> loan
    loan.age payment interest balance
 1:        0    5000     0.00 5000.00
 2:        1    -100    50.00 4950.00
 3:        2    -100    49.50 4899.50
 4:        3    -100    48.99 4848.49
 5:        4    -100    48.49 4796.98
 6:        5    -100    47.97 4744.95
 7:        6    -100    47.45 4692.40
 8:        7    -100    46.92 4639.32
 9:        8    -100    46.39 4585.71
10:        9    -100    45.87 4531.58

我可以通过for循环来解决问题,但是对于大型投资组合来说,它的工作效率会慢下来。对于上下文,使用年金公式比使用for循环(每个贷款2s对20ms)快300倍的贷款。

我已尝试将表格加入到自身中,并且我也尝试过在数据表1.9.5中新增的shift()函数,但我无法解决这个问题。强迫计算从上到下进行的方式,以便新的平衡在桌子上涟漪。

我的代码目前使用从年金公式中得出的一些财务数据计算出每个时期的余额,但如果利率在贷款中有所变化,那么这种方法就无法发挥作用。

感谢。

编辑:我认为这个问题已经解决了。来自的解决方案2b) G. Grothendieck下面给出了一个通用的解决方案,它既适用于这个简单的案例,也可以扩展到更复杂的场景。

1 个答案:

答案 0 :(得分:8)

1)尝试filter

loan[, c("interest", "balance") := 0][, 
     balance := c(filter(payment, 1.01, method = "recursive"))][,
     interest := c(0, diff(balance) - payment[-1])]

,并提供:

> loan
    loan.age payment interest  balance
 1:        1    5000  0.00000 5000.000
 2:        2    -100 50.00000 4950.000
 3:        3    -100 49.50000 4899.500
 4:        4    -100 48.99500 4848.495
 5:        5    -100 48.48495 4796.980
 6:        6    -100 47.96980 4744.950
 7:        7    -100 47.44950 4692.399
 8:        8    -100 46.92399 4639.323
 9:        9    -100 46.39323 4585.716
10:       10    -100 45.85716 4531.574

注意:最后一行可以写成:

         interest := .01 * c(0, balance[-.N])]

或在data.table的开发版本中:

         interest := .01 * shift(balance, fill = 0)[[1]]]

2)减少另一种可能性是:

f <- function(balance, payment) payment + 1.01 * balance

loan[, c("interest", "balance") := 0][, 
     balance := Reduce(f, payment, accumulate = TRUE) ][,
     interest := c(0, diff(balance) - payment[-1]) ]

2a)或者如果有一个rate列,并且已知payment除了第一个值(如问题中)之外是常量,那么以下工作。请注意,我们已将rate列设为常量,但只要rate的变量保持不变,即使payment变化,以下内容仍然有效:

loan$rate <- .01
g <- function(balance, rate) loan$payment[2] + (1 + rate) * balance

loan[, c("interest", "balance") := 0][, 
     balance := Reduce(g, rate[-1], init = payment[1], accumulate = TRUE) ][,
     interest := c(0, diff(balance) - payment[-1]) ]

2b)这允许paymentrate变化:

loan$rate <- .01
h <- function(balance, i) loan$payment[i] + (1 + loan$rate[i]) * balance

loan[, c("interest", "balance") := 0][, 
     balance := Reduce(h, .I[-1], init = payment[1], accumulate = TRUE) ][,
     interest := c(0, diff(balance) - payment[-1]) ]