Fit an exponential curve using nls with a custom data frame in R

喜你入骨 提交于 2019-12-25 03:55:33

问题


I have been through many questions on SO but I am not able to find a fix for my problem in related answers. I have a table like this stored as PAO1.data:

Name         P          AO
Prog1        0.654      59.702
Prog2        0.149      49.595
Prog3        0.505      50.538
Prog4        0.777      59.954
Prog5        0.237      49.611
Prog6        0.756      50.630
Prog7        0.560      118.014
Prog8        0.015      53.779
Prog9        0.789      68.096
Prog10       0.825      79.558

I tried to use nls to fit an exponential curve to the data.

df = data.frame(PAO1.data)
p = df$P
ao = df$AO
RMSE <- function(fit, act){
    sqrt(mean((fit - act)^2))
}

expmodel = nls(formula = p ~ exp(ao), data = df, start = list(ao = 0.01))
fit1 = fitted.values(expmodel)
err1 = RMSE(fit1, p)
plot(ao, p)
lines(ao, predict(expmodel))
print(err1)

When I try to run it, I get these warning messages while creating expmodel:

Warning messages:
1: In min(x) : no non-missing arguments to min; returning Inf
2: In max(x) : no non-missing arguments to max; returning -Inf

At the same time, I get this error at lines():

Error in xy.coords(x, y) : 'x' and 'y' lengths differ
Calls: lines -> lines.default -> plot.xy -> xy.coords

Another question I read on SO with the 'lengths differing' error actually had differing lengths in x and y. However, my x and y (here ao and p) have exactly the same number of values.

Please note, it is not likely that an exponential curve will actually be a good fit, but I am trying out several different models and I want to know how to use nls properly so I can do the same with other models.

Some related curve-fitting questions:

This question says that the starting data was the key. The smallest value for AO in my table is 0.015 and I chose 0.01, which is close enough in my opinion. This question asks about nls and the answer is given using a polynomial using lm. I specifically need to know how to use nls for a lot of complex models in the future and this will not work for me. This question looked promising but I am not able to find the problem in my code by looking at that question and answer - I have similar statements in my code too.

How do I do it?

Edit:

Here are screenshots of the solutions posted in the comments by Roland: (The actual dataset is bigger)

After changing the call to nls to expmodel = nls(formula = p ~ exp(beta * ao), data = df, start = list(beta = 0.01))

After sorting the AO values with lines(sort(ao), predict(expmodel))


回答1:


df <- read.table(text = "Name         P          AO
Prog1        0.654      59.702
                 Prog2        0.149      49.595
                 Prog3        0.505      50.538
                 Prog4        0.777      59.954
                 Prog5        0.237      49.611
                 Prog6        0.756      50.630
                 Prog7        0.560      118.014
                 Prog8        0.015      53.779
                 Prog9        0.789      68.096
                 Prog10       0.825      79.558", header = TRUE)

#use correct syntax:
expmodel = nls(formula = P ~ exp(beta * AO), data = df, start = list(beta = 0.01))

plot(P ~ AO, data = df)
#you could use lines after sorting, but this is more convenient:
curve(predict(expmodel, newdata = data.frame(AO = x)), from = 49, to = 120, add = TRUE)

Obviously this is not a good model for your data. As you know the exponential function goes through (0,1). You should consider adding an intercept.



来源:https://stackoverflow.com/questions/37389240/fit-an-exponential-curve-using-nls-with-a-custom-data-frame-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!