Reputation: 33
I'm trying to fit an exponential model to a set of data I have using R's nls method. The model in question is:
y=ae^(bx)
I get estimated start points by taking logs of both sides then finding the coefficients from a linear regression model, then pass them into nls. When I do this, nls throws up the "Missing value or an infinity produced when evaluating the model" error.
The model worked when I tested it with values that I'd set manually (a=1, b=1) but I want my code to work with more than just the test data. I've tried swapping the values of a and b around and also tried using selfStart methods (although I didn't fully understand them).
This is my code so far:
csvfile <- read.csv("testdata.csv")
col1<-unlist(lapply(csvfile[colnames(csvfile)[1]], log))
col2<-unlist(lapply(csvfile[colnames(csvfile)[2]], log))
a_start<-as.numeric(summary(lm(col2~col1))$coefficients[2])
b_start<-as.numeric(summary(lm(col2~col1))$coefficients[4])
f=as.formula(paste(as.name(colnames(csvfile)[1]),"~I(a*exp(b*",as.name(colnames(csvfile[2])),"))"))
expo<-nls(f,data=csvfile, start=list(a=a_start,b=b_start))
and this is the content of testdata.csv:
"x","y"
1,7
2,10
3,24
4,47
5,96
I was expecting to get a result back such that a=2.78545 and b=0.707868, which was what I got when I manually entered the start values.
Any and all help/advice is appreciated, thanks.
Upvotes: 2
Views: 452
Reputation: 6191
Welcome to SO.
I think this is due to a minor typing error. When you generate your formula with
f=as.formula(paste(as.name(colnames(csvfile)[1]),"~I(a*exp(b*",as.name(colnames(csvfile[2])),"))"))
then you are actually producing the formula
> f
x ~ I(a * exp(b * y))
I think you have swapped the x
and the y
around and the starting value for a needs to be back-transformed. At least, when you create the starting values from the logged variables then you model log(y)
as a function of log(x)
. If you do the following instead then it appears to work
> f=as.formula(paste(as.name(colnames(csvfile)[2]),"~I(a*exp(b*",as.name(colnames(csvfile[1])),"))"))
> expo<-nls(f,data=csvfile, start=list(a=exp(a_start),b=b_start))
> expo
Nonlinear regression model
model: y ~ I(a * exp(b * x))
data: csvfile
a b
2.7854 0.7079
residual sum-of-squares: 4.569
Number of iterations to convergence: 7
Achieved convergence tolerance: 1.099e-08
A few other comments: Why do you log the x's? log(a exp(bx)) = log(a) + bx
Also, you can write it more compact as
initial_model <- lm(log(y) ~ x, data=csvfile)
f <- as.formula(paste(as.name(colnames(csvfile)[2]),"~I(a*exp(b*",as.name(colnames(csvfile[1])),"))"))
expo <- nls(f, data=csvfile, start=list(a=exp(coef(initial_model)[1]),b=coef(initial_model)[2]))
Upvotes: 1