If you introduce a debugger in your function f, you'll see what's going on:
f <- function(balance, payment) { browser(); payment + int * balance; }
loan[, c("interest", "balance") := 0
][,balance := Reduce(f, payment, accumulate = TRUE)
]
# Browse[2]>
balance
# [1] 5000
# Browse[2]>
payment
# [1] -1000
# Browse[2]>
int
# [1] 1.127515 1.131305 1.149106 1.118575 1.087982
# Browse[2]>
payment + int * balance
# [1] 4637.577 4656.526 4745.531 4592.875 4439.911
### continue out, let it do its thing
loan
# loan.age payment interest balance
# 1: 1 5000 0 5000
# 2: 2 -1000 0 4637.577,4656.526,4745.531,4592.875,4439.911
# 3: 3 -1000 0 4228.940,4267.952,4453.119,4137.476,3830.544
# 4: 4 -1000 0 3768.195,3828.356,4117.106,3628.077,3167.563
# 5: 5 -1000 0 3248.698,3331.039,3730.992,3058.277,2446.252
loan$balance[2]
# [[1]]
# [1] 4637.577 4656.526 4745.531 4592.875 4439.911
What I think you mean is to use each int for each row of your table. This is not a natural thing with Reduce, unfortunately, so we'll have to rig it a little. I'll "zip" the payment and int vectors together with Map(list, payment, int), which will require a little bit of cleanup.
set.seed(2)
int <- rnorm(nT, mean = 0.1, sd = 0.02) + 1
int
# [1] 1.082062 1.103697 1.131757 1.077392 1.098395
# start fresh
loan <- data.table(loan.age = seq(0:(nT-1)), payment = c(5000, -rep(1000,(nT-1))))
f2 <- function(balance, payment) { browser(); payment[[1]] + payment[[2]] * balance[[1]]; }
loan[, c("interest", "balance") := 0
][,balance := Reduce(f2, Map(list, payment, int), accumulate = TRUE)
]
# Called from: f(init, x[[i]])
# Browse[1]>
debug at #1: payment[[1]] + payment[[2]] * balance[[1]]
# Browse[2]>
payment
# [[1]]
# [1] -1000
# [[2]]
# [1] 1.103697
# Browse[2]>
balance
# [[1]]
# [1] 5000
# [[2]]
# [1] 1.082062
# Browse[2]>
payment[[1]] + payment[[2]] * balance[[1]]
# [1] 4518.485
# Browse[2]>
### continue out until done
loan
# loan.age payment interest balance
# 1: 1 5000 0 <list>
# 2: 2 -1000 0 4518.485
# 3: 3 -1000 0 4113.827
# 4: 4 -1000 0 3432.206
# 5: 5 -1000 0 2769.918
loan$balance[[1]]
# [[1]]
# [1] 5000
# [[2]]
# [1] 1.082062
Obviously we can't have balance as a list-column ... so we can just extract and unlist it with another pipe-line:
f3 <- function(balance, payment) { payment[[1]] + payment[[2]] * balance[[1]]; }
# start fresh
loan <- data.table(loan.age = seq(0:(nT-1)), payment = c(5000, -rep(1000,(nT-1))))
loan[, c("interest", "balance") := 0
][,balance := Reduce(f3, Map(list, payment, int), accumulate = TRUE)
][,balance := unlist(c(balance[[1]][[1]], balance[-1]))
]
loan
# loan.age payment interest balance
# 1: 1 5000 0 5000
# 2: 2 -1000 0 4518.485
# 3: 3 -1000 0 4113.827
# 4: 4 -1000 0 3432.206
# 5: 5 -1000 0 2769.918
So finally:
# start fresh
loan <- data.table(loan.age = seq(0:(nT-1)), payment = c(5000, -rep(1000,(nT-1))))
loan[, c("interest", "balance") := 0
][,balance := Reduce(f3, Map(list, payment, int), accumulate = TRUE)
][,balance := unlist(c(balance[[1]][[1]], balance[-1]))
][,interest := c(0, diff(balance) - payment[-1])
]
loan
# loan.age payment interest balance
# 1: 1 5000 0.0000 5000.000
# 2: 2 -1000 518.4849 4518.485
# 3: 3 -1000 595.3416 4113.827
# 4: 4 -1000 318.3793 3432.206
# 5: 5 -1000 337.7118 2769.918