Search code examples
rfor-loopapplysapply

How to use apply when each calculated value depends on previous value


I have 3 columns:

  1. installment

  2. interest

  3. exposure

1st row goes like this

installment interest exposure

0          0        1000

Installment is 0 for 1st row and a constant figure afterwards. Let it be 100.

Interest of ith row = 0.5% * exposure of (i-1) th row

Exposure of ith row = exposure of (i-1)th row - (installment of ith row - interest of ith row)

installment interest   exposure

0           0          1000
100         0.005*1000 1000-(100-5)

current interest depends of previous exposure and current exposure depends on current interest.This should go on till exposure is 0. I have done this using a for loop in R. But my data is large and I don't want a for loop. So I need something like an apply or even faster method if possible

is there any other way to do this without a loop. I'm looking for a speedy process.


Solution

  • Looks like loan amortization, you can try to create a formula before coding it.

    < Unfortunately, I am not quite sure how to render LaTeX in SO's Markdown here. Sorry for the presentation. >

    Let L be starting loan amount, I be installment payment and r be the interest rate.

    At period, n=0, outstanding loan amount is L.

    At period, n=1, outstanding loan amount is (1+r)*L - I.

    At period, n=2, outstanding loan amount is (1+r)^2 * L - (1+r) * I - I.

    At period, n=3, outstanding loan amount is (1+r)^3 * L - (1+r)^2 * I - (1+r) * I - I.

    At period, n, outstanding loan amount is (1+r)^n * L - I * sum_{k=0}^{n-1} (1+r)^k.

    After which, it is a matter of coding this:

    amor <- function(L, r, I, nvec) {
        vapply(nvec, 
            function(n) {
                if (n < 1L) stop("n must be > 0.")
                L * (1+r)^n - I * sum((1+r)^(seq_len(n) -1L))
            },
            numeric(1))
    }
    amor(1000, r, 100, seq_len(12))
    

    output:

    [1]  905.00000  809.52500  713.57262  617.14049  520.22619  422.82732  324.94146  226.56617  127.69900   28.33749  -71.52082 -171.87843
    

    The next problem to tackle is "This should go on till exposure is 0". You can approximate the total number of periods using n * I > L * (1+r)^n

    maxN <- round(uniroot(function(n) I*n - (1+r)^n*L, c(1, 1000))$root)
    

    Then use replace to set those negative numbers to 0.

    Hopefully this helps.