Search code examples
rvectorsyntax-errornlsindexed

R Nonliner Least Squares (nls) function: Using indexed vectors as inputs?


I am trying to run the nls function in R using indexed vectors as inputs, however I am getting an error:

> a=c(1,2,3,4,5,6,7,8,9,10)
> b=c(6,7,9,11,14,18,23,30,38,50) #make some example data
>
> nls(b[1:6]~s+k*2^(a[1:6]/d),start=list(s=2,k=3,d=2.5)) #try running nls on first 6 elements of a and b
Error in parse(text = x, keep.source = FALSE) :
  <text>:2:0: unexpected end of input
1: ~
   ^

I can run it on the full vectors:

> nls(b~s+k*2^(a/d),start=list(s=2,k=3,d=2.5))
Nonlinear regression model
  model: b ~ s + k * 2^(a/d)
   data: parent.frame()
    s     k     d
1.710 3.171 2.548
 residual sum-of-squares: 0.3766

Number of iterations to convergence: 3
Achieved convergence tolerance: 1.2e-07

I am fairly certain that the indexed vectors have the same variable type as the full vectors:

> a
 [1]  1  2  3  4  5  6  7  8  9 10
> typeof(a)
[1] "double"
> class(a)
[1] "numeric"

> a[1:6]
[1] 1 2 3 4 5 6
> typeof(a[1:6])
[1] "double"
> class(a[1:6])
[1] "numeric"

I can run nls if I save the indexed vectors in new variables:

> a_part=a[1:6]
> b_part=b[1:6]
> nls(b_part~s+k*2^(a_part/d),start=list(s=2,k=3,d=2.5))
Nonlinear regression model
  model: b_part ~ s + k * 2^(a_part/d)
   data: parent.frame()
    s     k     d
2.297 2.720 2.373
 residual sum-of-squares: 0.06569

Number of iterations to convergence: 3
Achieved convergence tolerance: 1.274e-07

Furthermore, lm accepts both full and indexed vectors:

> lm(b~a)

Call:
lm(formula = b ~ a)

Coefficients:
(Intercept)            a
     -4.667        4.594

> lm(b[1:6]~a[1:6])

Call:
lm(formula = b[1:6] ~ a[1:6])

Coefficients:
(Intercept)       a[1:6]
      2.533        2.371

Is there a way to run nls on indexed vectors without saving them in new variables?


Solution

  • Use subset . (It would also be possible to use the weights argument giving a weight of 1 to each of the first 6 observations and 0 to the rest.)

    Also you might want to use the plinear algorithm to avoid having to give the starting values for the two parameters that enter linearly. In that case provide a matrix on the RHS with column names s and k such that its first column multiplies s and the second column multiplies k.

    nls(b ~ cbind(s = 1, k = 2^(a/d)), subset = 1:6, start = list(d = 2.5), 
      algorithm = "plinear")
    

    giving:

    Nonlinear regression model
      model: b ~ cbind(s = 1, k = 2^(a/d))
       data: parent.frame()
         d .lin.s .lin.k 
     2.373  2.297  2.720 
     residual sum-of-squares: 0.06569
    
    Number of iterations to convergence: 3 
    Achieved convergence tolerance: 7.186e-08