Search code examples
rnls

nesting dataframe references in lm vs nls functions


Say I have some data, as a data frame:

GSM<- c(NA, 0.11, 0.12, 0.05, 0.06, 0.43, 0.44, 0.32, 0.29, 0.22, 0.24)
enz<- c(18.73287, 48.92596, 51.78783, 12.07112, 17.98551,NA,NA, 62.74149, 25.92524, 17.25657, 32.10908)
dat<-data.frame(GSM,enz)

I then create a function that references a data frame, and columns within that data frame, and returns the output of a linear regression model:

lmfit<-function(data,x,y){
    mod<-lm(log(data[[y]])~data[[x]])
    out<-coef(mod)
    return(out)
}

x<-'GSM'
y<-'enz'
lmfit(dat,x,y)

So far so good. This returns an intercept and a slope. I then run the same type of function, but with an nls fit, like this:

VKfit<-function(data,x,y,v.start,k.start) {
    mod<- nls(log(data[[y]])~Vm*data[[x]]/(K+data[[x]]),start=list(Vm=v.start,K=k.start))
    out<-coef(mod)
    return(out)
}

x<-'GSM'
y<-'enz'
v.start<-3
k.start<-0.09
VKfit(dat,x,y,v.start,k.start)

This prints the error:

Error in parse(text = x) : <text>:2:0: unexpected end of input
1: ~ 
   ^

What am I doing wrong here? If I run:

mod<- nls(log(enz)~Vm*GSM/(K+GSM),data=dat,start=list(Vm=v.start,K=k.start))
coef(mod)

I can fit the model and return coefficients no problem, so the data and starting values in nls do not seem to be the issue.


Solution

  • This should work (source):

    VKfit <- function(data, x, y, v.start, k.start){
      eqn <- sprintf("log(%s) ~ Vm * %s / (K+%s)", y, x, x)
      mod <- nls(eqn, data=data, start=list(Vm=v.start,K=k.start))
      out <- coef(mod)
      return(out)
    }
    
    x <- 'GSM'
    y <- 'enz'
    # which gives "log(enz) ~ Vm * GSM / (K+GSM)" for eqn in the function
    v.start <- 3
    k.start <- 0.09
    cf2 <- VKfit(dat,x,y,v.start,k.start)
    cf2
    #         Vm          K 
    # 3.86761821 0.01822488 
    
    # Comparison
    mod <- nls(log(enz)~Vm*GSM/(K+GSM),data=dat,start=list(Vm=v.start,K=k.start))
    cf1 <- coef(mod)
    
    all.equal(cf1, cf2)
    # [1] TRUE