Reputation: 3081
I have the following problem that I would like to vectorise in R with data.table if possible. Since R is rather slow with for loops, I think in my case vectorisation is a must (over 500 observations).
Below I show a dummy example of what I would like to vectorise. Consider the following code:
library(data.table)
test <- data.table(Person = c("A", "B"),
Interest = c(0.02, 0.03),
Principal = c(100, 200),
Duration = c(3, 10),
Deduction = c(2, 3))
Here, I would like to produce the following table, where each calculation depends on two of properties of that person and the previous calculation result (starting from the principal amount).
So for person A I would get: 100, (100 - 2 (Deduction)) * (1 + 0.02 (Interest)). This would result in the following serie: 100, 99.96, 99.9192, 99.87758 for period 0, 1, 2, 3.
For person B, the duration is a bit longer, namely 10, so I will get the following serie, with the properties of person B:
200, 200.94, 201.8988, 202.876776, 203.8743115, 204.8917978, 205.9296337, 206.9882264, 208.0679909, 209.1693507 210.2927377
With both series in a table, so the final table would be 2 times 10 long, with all other spaces filled in by NA when the duration is less than the maximum duration that occurs in the input table.
The main problem remains the vectorisation, I am not sure how to vectorise this using data.table in R.
Upvotes: 0
Views: 69
Reputation: 66819
There's a closed-form solution.
res = test[, .(
t = 0:Duration,
v = Principal*(1+Interest)^(0:Duration) - Deduction*cumsum(c(0, (1+Interest)^(1:Duration)))
), by=Person]
Person V1
1: A 100.00000
2: A 99.96000
3: A 99.91920
4: A 99.87758
5: B 200.00000
6: B 202.91000
7: B 205.90730
8: B 208.99452
9: B 212.17435
10: B 215.44959
11: B 218.82307
12: B 222.29776
13: B 225.87670
14: B 229.56300
15: B 233.35989
Misc comments:
You should generally look for this kind of translation before getting to questions of how to code it.
To insert the missing values, there's res[CJ(Person = Person, t = t, unique=TRUE), on=.(Person, t)]
.
As @Nicolas2 pointed out, your results for Person B seem to be wrong.
Upvotes: 3