I have a problem in solving a number of non-linear equations with nleqslv
in R in order to solve for a distance-to-default measure. This is my first R code, so I am still struggling with some problems. My code looks like this (miniaturized to a three-case-data.frame):
library("nleqslv")
D <- c(28000000, 59150000, 38357000)
VE <- c(4257875, 10522163.6, 31230643)
R <- c(0.059883, 0.059883, 0.059883)
SE <- c(0.313887897, 0.449654737, 0.449734826976691)
df <- data.frame(D, VE, R, SE)
for(i in 1:nrow(df)){
fnewton <- function(x){
y <- numeric(2)
d1 <- (log(x[1]/df$D[i])+(df$R[i]+x[2]^2/2))/x[2]
d2 <- d1-x[2]
y1 <- df$VE[i]-(x[1]*pnorm(d1)-exp(-df$R[i])*df$D[i]*pnorm(d2))
y2 <- df$SE[i]*df$VE[i]-pnorm(d1)*x[2]*x[1]
y
}
xstart <- c(df$VE[i], df$SE[i])
df$VA[i] <- nleqslv(xstart, fnewton, method="Newton")$x[1]
df$SA[i] <- nleqslv(xstart, fnewton, method="Newton")$x[2]
i=i+1
}
My problem is, that my code only gives me one solution, meaning that my loop does not work properly in the first place. The loop should overcome the fact, that fnewton
is a vector of length 2 in the first place, but my data (or my example) is a longer vector than 2. I tried some things but I cannot handle the problem, I think there is a simple solution for this, but I do not see my mistake.
The code by
skwon
can be made more efficient by defining thefnewton
function once outside the for loop and by putting the variablesdf
andi
in the arguments. Like soand then change the loop to this
If the function
fnewton
becomes more complicated you can also use packagecompiler
to speed it up (a little bit).Finally you really should test that
nleqslv
has in fact found a solution by testing ifz$termcd==1
. If not then skip the assigning of thez$x
values. I'll leave that for you.There are some simple mistakes in code.
1) As mra68 commented, change y1, y2 in fnewton function to
y[1]
,y[2]
.2) remove last line
i=i+1
(Nexti
is automatically mapped by the linefor(i in 1:nrow(df)){
.)3) (Optional) Initialize df with VA, SA specified.
Here's final working code: