0

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)))
Toy L
  • 55
  • 6

1 Answers1

1

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))

Added

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))
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • That is a fine solution. I am, however, trying to extrapolate your approach to my work which is similar but different in the formula: `summary(nls(formula= C1~g*(( (1/ (1 + exp((g)*((1/p)-(1/(p)))))) -(1/ (1 + exp((g)*((1/lag(p))-(1/(p)))))) ) /(diff(p))),data=df,trace=F, start=list(g=5),control=nls.lm.control(maxiter=1000)))`. However,making my equivalent of your suggested y1<-df$y[-1] does not seem to solve the issue. Is this because of the `lag` involved? The `df` and variables used are identical to that in the code in the mother question. – Toy L Feb 03 '22 at 00:10
  • 1
    Have moved comment to Added section and added improvements. – G. Grothendieck Feb 03 '22 at 15:01
  • What do you mean by linear in the single parameter `g`? Do you mean `g^n;n=1`? – Toy L Feb 11 '22 at 00:18
  • If you are referring to (3) in the answer then if the right hand side is linear in the parameters then it is a linear rather than a nonlinear problem and although nls can be used it is overkill and we can use lm instead. This has the advantage that starting values are not needed. The right hand side is linear in the parameters p1, p2, ...,, pn if the nls right hand side is of the form p1 * x1 + p2 * x2 + ... + pn * xn where p1, p2, ..., pn are the parameters we are optimizing over and x1, ..., xn are expressions which do not involve any of the parameters but may involve the data. – G. Grothendieck Feb 11 '22 at 13:11