-1

I have written a function for amortising a loan given the loan characteristics and for providing me with the present value of the payment cash flows:

mortgage<-function(P,I,L,amort,periodicity,n,residual,discount){


if(periodicity<-TRUE){i<-I/n}else{i<-I}
N<-n*L 
payment<- -((residual-(P*((1+i)^N)))/((((1+i)^N)-1)/i))
pay<<-payment
if(amort==T){
Pt<-P
currP<-NULL
while(Pt>=residual){
H<-Pt*i 
C<- payment-H
Q<-Pt-C
Pt<-Q
currP<-c(currP,Pt)}
monthP<-c(P,currP[1:(length(currP)-1)])-currP

adFmonth<<-data.frame(
  Amortization=c(P,currP[1:(length(currP)-1)]),
  Payment<-monthP+c((pay-monthP)[1:(length(monthP)-1)],0),
  Principal=monthP,
  Interest=c((pay-monthP)[1:(length(monthP)-1)],0),
  Time=sort(rep(1:ceiling(L*n/n),n))[1:length(monthP)]
)
adFmonth<<-adFmonth
}

AssetValue<-pv(discount/n,N,residual,pay)

return(AssetValue)
}

Given a set of (different) loans and a matrix containing the value of each function argument per loan, I would now like to create a loop, as that the function loops through each column of the matrix and gives me the output of the function.

Can anyone help me with that endeavour?

Thank you very much.

  • You've written a function that is difficult to program with because it uses global assignment with `<<-` instead of just returning the results. You should rewrite your function to not use `<<-` and just return everything - use a `list()` if you need to return multiple objects. Then the `for` loop should be trivial, it would be best if you showed an attempt. `results = list(); for(i in 1:ncol(your_matrix)) { results[[i]] = mortgage(your_matrix[1, i], your_matrix[2, i], ...)}` – Gregor Thomas Nov 09 '17 at 16:11
  • Your answer seems appealing, however if I do as stated, I get the following error message: Error in I/n : non-numeric argument to binary operator This makes no sense as both are defined as a number in my formula. Is it possible that when I import a CSV file with the same values from Excel, that the values are no longer treated as numerical? If yes, how can I change that? – David Raths Nov 09 '17 at 16:46
  • 1
    You can make a reproducible example. [See here for a complete guide](https://stackoverflow.com/q/5963269/903061). I can't help more based on the information you have provided.Importing a CSV, you almost certainly have a `data.frame`, not a `matrix`. Its entirely possible that your data is poorly imported and non-numeric - you can find plenty of questions about that. Look at `str(your_data)` to see the classes of everything. – Gregor Thomas Nov 09 '17 at 17:00

1 Answers1

1

I would definitely advise you to take @Gregor's advice in the comment on your first post - avoid the global assignment within a function. That said, here is how I would approach your problem:

Assumption: For your data you are using a dataframe where each row maps to a unique loan and each column entry has a parameter (named A, B, and C in my examples) for the corresponding row.

My simple example should be easily extendable to your problem:

df <- data.frame(A=c(1,0,3),B=c(3,3,3),C=c(4,3,0)) # Replace with your data

# Replace with your function
myFn <- function(A,B,C) {
  x <- (A+B)/C
  return(x)
  }

# Appends 'answer' to your dataframe with the answer correctly mapped to each loan
df$answer <- with(df,myFn(A=A,B=B,C=C))

If you wish to have multiple 'answers' returned, change the code to be like:

df <- data.frame(A=c(1,0,3),B=c(3,3,3),C=c(4,3,0)) # Replace with your data

# Replace with your function
myFn <- function(A,B,C) {
  x <- (A+B)
  y <- C
  z <- x/y
  return(data.frame(A=A,B=B,C=C,numerator=x,denominator=y,answer=z))
  }

# Creates a new dataframe from the original with each 'multivariate' answer correctly mapped to each loan
df2 <- with(df,myFn(A=A,B=B,C=C))

# Examine your output:
head(df2)
str(df2)

There are probably more elegant solutions, but this should serve your purposes.

Nate
  • 364
  • 1
  • 5