Search code examples
rdynamicnls

How can I dynamically populate start values in nls?


I'm feeding dynamic inputs into nls(), but I can't get the start argument to work. It seems I don't know how to feed it the right object. I need the object vars in the right structure to satisfy the start argument.

In this example, my starting values are stored in vars. I've tried reshaping it as well as messing with the object class using as.vector, as.array and as.matrix, among others, without success.

#need this package for acm.disjonctif()
library(ade4)

#get some fake data going for an ad measurement scenario
durta <- data.frame (  
    "impact"=c(150,150,350,50,150,150,  140,160,330,80,130,170)
  , "spend"= c(1000,1200,2300,500,1300,1000,  1900,1200,2000,500,1000,1400)
  , "adtitle"=c("zip","bang","boom","zip","bang","boom",  "zip","bang","boom","zip","bang","boom")
  , "network"=c("NBC","TNT","NBC","TNT","NBC","TNT",  "NBC","TNT","NBC","TNT","NBC","TNT")
  )

#making each element from network and adtitle into its own binary dimension
factors <- acm.disjonctif(durta[,3:4])

#getting rid of pesky byproducts
colnames(factors) <- gsub("network.","",gsub("adtitle.","",colnames(factors)))

#going to feed this to nls
input <- data.frame(cbind("impact"=durta$impact,"spend"=durta$spend,factors))

#also need to send these starting values
vars <- data.frame("var"=as.array(letters)[1:ncol(factors)],"start"=0)

#pasting a dynamic formula based on 'input' using as.formula works fine
#tried a similar solution for the starting values, failed 
fit <-  nls(   
  as.formula(paste(paste("impact ~ spend*(", paste(paste(vars[,1],"*"),noquote(colnames(input[3:ncol(input)])), collapse="+")),")"))
  , data=input
  , algorithm = "port"
  , start = vars
  #, start = c(a=.1,b=.3,c=0.3,d=-.9,e=.2)
  #          ^ this version works
)

If the start argument is satisfied, then I should get this (minor) error:

Error in nlsModel(formula, mf, start, wts, upper) : singular gradient matrix at initial parameter estimates

When I replace the working static code with var, I get this:

Error in nls(as.formula(paste(paste("impact ~ spend*(", paste(paste(vars[, : parameters without starting value in 'data': e

I already put some sensible starting values in the static version to deal with that first error for this contrived example, but it still throws it. So be it. That's not my concern.


Solution

  • start needs to be a named list. Thus

    start = setNames(as.list(vars$start), vars$var)
    

    seems to do what you want (takes the vector of values in vars$start, converts it to a list, and uses the corresponding elements of vars$var as its names).

    For what it's worth, it looks like you could fit this particular model with lm(impact/spend ~ ., data=input) ...