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