Question: Thank you in advance! does nlsLM
not work with diff
? I am simply trying to do
g*(p[i]-p[i-1])/(x[i]-x[i-1])
and use nlsLM
to find the value of fitting parameter g that can fit y
I use diff
without nlsLM
as follows,
`g*diff(df$p)/diff(df$x)`
and it works just fine:
`[1] 0.4 3.0 3.0`
However, when I use it with nlsLM
, it does not work and I get the following:
`Error in qr(.swts * attr(rhs, "gradient")) :
dims [product 3] do not match the length of object [4]
In addition: Warning messages:
1: In lhs - rhs :
longer object length is not a multiple of shorter object length
2: In lhs - rhs :
longer object length is not a multiple of shorter object length
3: In lhs - rhs :
longer object length is not a multiple of shorter object length
4: In lhs - rhs :
longer object length is not a multiple of shorter object length
5: In lhs - rhs :
longer object length is not a multiple of shorter object length
6: In lhs - rhs :
longer object length is not a multiple of shorter object length
7: In lhs - rhs :
longer object length is not a multiple of shorter object length
8: In .swts * attr(rhs, "gradient") :
longer object length is not a multiple of shorter object length`
Code:
# Packages:
library(tidyverse)
library(minpack.lm)
# undoing tidyverse's masking effects( Courtesy of user Kat)
filter <- dyplr::filter
lag <- dplyr::lag
#df
df<-data.frame(x=c(9,14,15,17),p=c(11,13,16,22),y=c(16,19,25,35))
#object
g<-5
#nlsLM run: finding fitting parameter g's value
summary(nlsLM(formula=y~g*diff(p)/diff(x),
data=df,trace=F,
start=list(g=5),control=nls.lm.control(maxiter=1000)))
We assume you are interested in the following least squares model where n is nrow(df)
y[i] ~ g * (p[i] - p[i-1]) / (x[i] - x[i-1]) for i = 2, ..., n
1) nlsLM Now diff(x)
is one shorter than x
since for the first element there is no prior element to subtract so use this
y1 <- df$y[-1]
nlsLM(y1 ~ g * diff(p) / diff(x), df, start = list(g = 5))
giving:
Nonlinear regression model
model: y1 ~ g * diff(p)/diff(x)
data: df
g
10.33
residual sum-of-squares: 273
Number of iterations to convergence: 2
Achieved convergence tolerance: 1.49e-08
2) nls Note that we could have used nls
y1 <- df$y[-1]
nls(y1 ~ g * diff(p) / diff(x), df, start = list(g = 5))
3) lm and since this is linear in the single parameter g
we could have used lm
as well.
lm(y[-1] ~ I(diff(p) / diff(x)) + 0, df)
4) dyn The dyn package can handle this automatically with lm
and other certain regression functions that use model.frame
using zoo or ts.
library(dyn)
dyn$lm(y ~ I(diff(p) / diff(x)) + 0, zoo(df))
Regarding the problem in the comments an error in that comment was introduced by faulty alignment. Try this which for me converges in 6 iterations.
y1 <- df$y[-1]
p1 <- df$p[-1]
pL <- df$p[-nrow(df)]
fo <- y1 ~ g*(( (1/ (1 + exp((g)*((1/p1)-(1/(p1)))))) -
(1/ (1 + exp((g)*((1/pL)-(1/(p1)))))) ) /(p1-pL))
nls(fo, start = list(g = 5))