Call nls from within a function in R, passing a user-specified function with any number of arguments

If a character string or function name is passed set FUN to the name of the function as a character string; otherwise, use "fit.fun". Then create the formula argument as a character string, convert it to an actual R formula and then run nls.

fit_nls <- function(d, x, FUN, start) {
  FUN <- if (length(match.call()[[4]]) > 1) {
    fit.fun <- match.fun(FUN)
    "fit.fun"
  } else deparse(substitute(FUN)) 
  fo <- as.formula(sprintf("x ~ %s(d, %s)", FUN, toString(names(start))))
  nls(fo, start = start)
}

Tests

with(df, fit_nls(d, x, "exp_fun", list(r = .01)))
## Nonlinear regression model
##   model: x ~ exp_fun(d, r)
##    data: parent.frame()
##      r 
## 0.1968 
##  residual sum-of-squares: 1.319
##
## Number of iterations to convergence: 11 
## Achieved convergence tolerance: 6.254e-06

with(df, fit_nls(d, x,  function(d, r){d^r}, start = list(r = .1)))
## Nonlinear regression model
##   model: x ~ fit.fun(d, r)
##    data: parent.frame()
##     r 
## 96.73 
##  residual sum-of-squares: 4.226
##
## Number of iterations to convergence: 22 
## Achieved convergence tolerance: 7.429e-06

with(df, fit_nls(d, x, exp_fun, list(r = .01)))
## Nonlinear regression model
##   model: x ~ exp_fun(d, r)
##    data: parent.frame()
##      r 
## 0.1968 
##  residual sum-of-squares: 1.319
##
## Number of iterations to convergence: 11 
## Achieved convergence tolerance: 6.254e-06