0

I have the following code to fit a sigmoidal function to my data:

nlsLM(mepAMP ~ plateau / (1 + exp(slope*(S50 - pMSO))), 
      data = df,
      start = list(plateau = 7, S50 = 100, slope = 0.15)

From my understanding, nlsLM (much like base nls available in r) has the option of selecting upper and lower bounds for the data. I'd specifically like to constrain the plateau to ≤8 mV to provide a physiologically plausible approximation of that parameter. Is there a way to constrain just one parameter? I've seen some posts where they specify upper = c(1000, 1) or something along those lines, but I'm not sure if that constrains all parameters and how I could specify plateau.

I've tried upper = c(8), but that gives me the following error:

Error in nls.lm(par = start, fn = FCT, jac = jac, control = control, lower = lower,  : 
  length(upper) must be equal to length(par)

I can't seem to find the proper syntax for setting the upper bound and would appreciate any guidance.

EDIT:

Thank you Allan for your help. I included upper = c(plateau = 8, S50 = Inf, slope = Inf) when I have multiple subjects, however, this seems to change not only the model fits where the plateau did go over 8, but also those that were nowhere close to that. Is this normal? I would think that it wouldn't touch the model fitting for those whose plateau was already below the constraint.

Before: enter image description here

After: enter image description here

A.R.
  • 51
  • 5

1 Answers1

1

You need to use a named vector. The vector must contain upper limits for all the parameters. If you only want to set an upper parameter on one of the values, set the others to Inf

library(minpack.lm)

nlsLM(mepAMP ~ plateau / (1 + exp(slope*(S50 - state))), 
                         data = df, 
                         start = list(plateau = 1, S50 = 1, slope = 1),
                         upper = c(plateau = 3, S50 = Inf, slope = Inf)) 
#> Nonlinear regression model
#>   model: mepAMP ~ plateau/(1 + exp(slope * (S50 - state)))
#>    data: df
#> plateau     S50   slope 
#>   3.000   5.912   1.014 
#>  residual sum-of-squares: 1.259
#> 
#> Number of iterations to convergence: 13 
#> Achieved convergence tolerance: 1.49e-08

Created on 2023-08-25 with reprex v2.0.2


Data used - taken from previous question

df <- structure(list(mepAMP = c(0.38117575, 0.11300747, 0.37239499, 
0.51321839, 0.56851893, 1.73259296, 2.08146847, 2.80090151, 3.04446933, 
2.67647473, 3.87695509), state = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 
10, 11)), row.names = c(NA, -11L), class = "data.frame")
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thank you once again for your help. I've edited my original post with a problem that came up as a result of this (or perhaps not a problem and just how the model works with constraints?). – A.R. Aug 25 '23 at 17:14