Reputation: 343
I'm trying to use nls(), but the error in the question was made.
Following is the sample data set resembles the original one:
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, rh1[-c(1)]),
ta1 = ta1,
ta2 = c(NA, ta1[-c(1)]),
y1 = y1,
y2 = c(NA, y1[-c(1)]))
df_test = df_test[-c(1), ] # this function cannot estimate for the first value
where rh is relative humidity of the air, ta is air temperature in K, and y is moisture content of an object. 1 means today's value; 2 means yesterday's value.
I'm trying to estimate y using y2, rh1&2 and ta1&2 by a model below:
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))
Coef1, 2, and 3 are the parameters to be estimated.
The initial values were determined by manual calculation for the first row of the data.
But this script made the error in the title.
Missing value or an infinity produced when evaluating the model
I also tried using minpack.lm::nlsLM() function according to the link below:
nls troubles: Missing value or an infinity produced when evaluating the model
library(minpack.lm)
nlsLM(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,
start = list(coef1 = 0.7,
coef2 = 0.15,
coef3 = 0),
upper = c(exp(-0.00005), Inf, Inf),
lower = c(exp(-0.5), Inf, Inf))
but still got the same error.
Upvotes: 1
Views: 3551
Reputation: 8837
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)
Upvotes: 3