nls troubles: Missing value or an infinity produced when evaluating the model
minpack.lm to the rescue:
library(minpack.lm)
curve.nlslrc = nlsLM(photolrc ~ Am*(1-((1-(Rd/Am))^(1-(PARlrc/LCP)))),
start=list(Am=(max(photolrc)-min(photolrc)),
Rd=-min(photolrc),
LCP= (max(photolrc)-1)),
data = curvelrc)
coef(curve.nlslrc)
# Am Rd LCP
#8.011311 1.087484 -20.752957
plot(photolrc ~ PARlrc, data = curvelrc)
lines(0:1300,
predict(curve.nlslrc,
newdata = data.frame(PARlrc = 0:1300)))
If you pass start = list(Am = 8, Rd = 1, LCP = -20)
to nls
you also get a successful fit.
I don't know if the parameter values are sensible estimates considering the science behind this. Can LCP be negative?
R - NLS Error 'Missing value or an infinity produced when evaluating the model'
Use the plinear
algorithm. In that case the right hand side and starting values should omit case_networks
and its value will be reported as .lin
.
fm <- nls(cases ~ r0^(t/5), data = us_jh_cases, alg = "plinear",
start = list(r0 = 2.5))
fm
giving:
Nonlinear regression model
model: cases ~ r0^(t/5)
data: us_jh_cases
r0 .lin
1.094e+00 1.513e+05
residual sum-of-squares: 9.836e+12
Number of iterations to convergence: 10
Achieved convergence tolerance: 6.719e-06
Graph
plot(cases ~ t, us_jh_cases, pch = ".", cex = 2)
lines(fitted(fm) ~ t, us_jh_cases, col = "red") # fit shown in red
nls() in R: Missing value or an infinity produced when evaluating the model
There are several issues here.
First off: your lagged values aren't really lagged. Take a look at df_test
and you will se that the 1
's and 2
's are identical.
This will give you lagged values:
set.seed(1)
rh1 <- rnorm(301, 0.75, 0.1)
rh1[rh1 > 1] <- 1
ta1 <- rnorm(301, 302, 3)
y1 <- rnorm(301, 0.2, 0.05)
df_test <- data.frame(
rh1 = rh1,
rh2 = c(NA, head(rh1, -1)),
ta1 = ta1,
ta2 = c(NA, head(ta1, -1)),
y1 = y1,
y2 = c(NA, head(y1, -1))
)
df_test <- df_test[complete.cases(df_test), ]
Next:
Missing value or an infinity produced when evaluating the model
Means just that, and my eyes immediately fix on the log
s in your expression. We all know that taking the log of a negative number is undefined, as is the log of 0, although it is often returned as infinity.
Let's take a look at those expressions
ex1 <- with(df_test, log(-8.2 * ta2 * log(rh2) / 18))
ex2 <- with(df_test, log(-8.3 * ta1 * log(rh1) / 18))
If you look at ex1
and ex2
you will see that both contain a -Inf
. Now there's your culprit. But how can we fix this? Let's see which rows in your data gives rise to this.
df_test[which(is.infinite(ex1 + ex2)),]
# rh1 rh2 ta1 ta2 y1 y2
# 274 1.0000 0.66481 304.5453 300.5972 0.20930 0.17474
# 275 0.7656 1.00000 304.9603 304.5453 0.20882 0.20930
Interesting, they are right next to each other, and they both contain a 1
. What's log(1)
? What happens if you multiply it by something and take the log of the product?
Let's make sure rh1
and rh2
is always less than 1
set.seed(1)
rh1 <- rnorm(301, 0.75, 0.1)
rh1[rh1 > 0.99] <- 0.99
ta1 <- rnorm(301, 302, 3)
y1 <- rnorm(301, 0.2, 0.05)
df_test <- data.frame(
rh1 = rh1,
rh2 = c(NA, head(rh1, -1)),
ta1 = ta1,
ta2 = c(NA, head(ta1, -1)),
y1 = y1,
y2 = c(NA, head(y1, -1))
)
df_test <- df_test[complete.cases(df_test), ]
But we're still not done. If you run your nls()
call now you'll get the error
Convergence failure: initial par violates constraints
And the cause is obvious if you look at the values you specify for your coefficients constraints. coef2
and coef3
has lower constraints set to infinity! That doesn't make sense. "initial par violates constraints" usually means that the start values aren't within the constraints, which is definitely the case here. If we change them to negative infinity everything works fine.
nls(y1 ~
coef1 ^ 2 * y2 +
coef1 * (1 - coef1) *
(coef2 + coef3 * log(-8.3 * ta2 * log(rh2) / 18)) +
(1 - coef1) *
(coef2 + coef3 * log(-8.3 * ta1 * log(rh1) / 18)),
data = df_test,
algorithm = "port",
start = list(coef1 = 0.7,
coef2 = 0.15,
coef3 = 0),
upper = c(exp(-0.00005), Inf, Inf),
lower = c(exp(-0.5), -Inf, -Inf)
)
# Nonlinear regression model
# model: y1 ~ coef1^2 * y2 + coef1 * (1 - coef1) * (coef2 + coef3 * log(…
# data: df_test
# coef1 coef2 coef3
# 0.6065 0.2569 -0.0170
# residual sum-of-squares: 1.058
# Algorithm "port", convergence message:
# both X-convergence and relative convergence (5)
nls missing value or infinity produced
If I understand what nls
is doing, it is estimating the values of parameters a
and b
in your case. Therefore there is no need to have start values for variables Volume
and Height
. These are simply the values in the dataset. If you remove them from the start
argument, the error goes away and you get a model.
model <- function(data){
nls(Volume~ a * (Height^b), data=data, start=c(a = 1, b = 1))
}
df %>% group_by(Site) %>% nest() %>%
mutate(mod= map(.x=data, model))
Why does nls return Missing value or an infinity produced when evaluating the model in this instance?
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]))
Why does nls give me an error when called from within ggplot?
When you change your scale, the formula also needs to be changed. Here is a possible solution, although I somehow cannot get confidence intervals to work.
myEquation=y ~ min+((max-min)/(1+10^(ec50-(x))))
ggplot(data=myData,aes(x=x,y=y))+geom_point()+scale_x_log10()+
geom_smooth(method="nls", formula = myEquation, start = startingGuess, se=FALSE)
UPDATE: Apparently the reason why confidence intervals do not work, is because standard errors are not currently implemented in predict.nls
. Therefore ggplot
also cannot display confidence intervals.
Related Topics
Setting Working Directory: Julia Versus R
Let Each Plot in Facet_Grid Have Its Own Y-Axis Value
How to Scrape a Table with Rvest and Xpath
R Shiny: How to Write Loop for Observeevent
Using Override.Aes() in Ggplot2 with Layered Symbols (R)
How to Prevent User from Setting the End Date Before the Start Date Using the Shiny Daterangeinput
Subsetting R Array: Dimension Lost When Its Length Is 1
Preview a Saved Png in an R Device Window
How to Get a List of All Possible Partitions of a Vector in R
Fastest Way to Read Large Excel Xlsx Files? to Parallelize or Not
Height' Must Be a Vector or a Matrix. Barplot Error
Build Word Co-Occurence Edge List in R
Replace Every Single Character at the Start of String That Matches a Regex Pattern
R Equivalent of Stata Local or Global MACros
Numbered Code Chunks in Rmarkdown
Create Fillable PDF Textbox via R
Is There an Alternative to "Revalue" Function from Plyr When Using Dplyr