I want to fit the points below with the function whose first guess is represented by the line:
But I get the following error message:
Error in nls(y ~ A * (1 + erf(E * B * (x - C)/sqrt(2))) * dnorm(B * (x - : gradiente singular
Traceback:
1. nls(y ~ A * (1 + erf(E * B * (x - C)/sqrt(2))) * dnorm(B * (x -
. C)) + D, data = fdata, start = list(A = A0, B = B0, C = C0,
. D = D0, E = E0))
Here's my code:
erf <- function(x) 2 * pnorm(x * sqrt(2)) - 1
x = c(0.275, 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.675, 0.725, 0.775, 0.825, 0.875, 0.925, 0.975)
y = c(33, 69, 48, 57, 51, 46, 36, 42, 26, 22, 22, 18, 16, 9, 5)
plot(x, y, xlim=c(0,1))
fdata = data.frame(x = x, y = y)
# Initial parameter values:
A0 = 1.3*max(y); B0 = 3.8*max(x); C0 = 1.0*x[which.max(y)]; D0 = 0.0; E0 = 4.0
# Plot curve with initial parameter values:
xfit0 = seq(from=0.0, to=1.0, length.out=100)
yfit0 = A0*(1+erf(E0*B0*(xfit0-C0)/sqrt(2)))*dnorm(B0*(xfit0-C0))+D0
lines(xfit0, yfit0, lwd=3)
# Do the fit:
fit <- nls(y~A*(1+erf(E*B*(x-C)/sqrt(2)))*dnorm(B*(x-C))+D, data = fdata, start = list(A = A0, B = B0, C = C0, D = D0, E = E0))
lines(fdata$x, predict(fit), col="red", lwd=2)
Why can't nls
converge even for such a close initial guess?
There aren't enough points to get a decent fit, particularly in some regions of the graph. Add some points using spline interpolation and then fit. To do that replace the last two lines of code in the question with these:
fdata.s <- spline(fdata)
fit <- nls(y~A*(1+erf(E*B*(x-C)/sqrt(2)))*dnorm(B*(x-C))+D, data = fdata.s,
start = list(A = A0, B = B0, C = C0, D = D0, E = E0))
lines(fdata.s$x, fitted(fit), col="red", lwd=2)