"object not found" inside a function: nlmer edition

Over the past few hours, I've found a few questions here regarding an R script that works fine outside of a function, but returns an "object not found" argument for an argument after refactoring the code to include functions. Unfortunately, the resolution for these errors seems to be very package and context dependent, so I have to throw my own nlmer-specific problem into the battle.

In short: I would like to run the nlmer model several times, but with a slightly different model specification each time. I have verified that the model works as stated outside of any function. I wrote a function that takes a data table and a formula (in string form) and runs the model, but returns an error that my model formula is "not found", although the variable "model_formula" is definitely in the function namespace.

Example:

# set up toy dataset
data <- data.table(patient_id=c(rep("pat_1", 10), rep("pat_2", 10), rep("pat_3", 10)),
                   agesero=c(rep(25,10), rep(19, 10), rep(34, 10)))
data$row <- as.numeric(rownames(data))
data[, variable:= ifelse(row%%10==0, "observed_survival", "vl")]
data[, M_visit_time:= ifelse(variable=="vl", row/6 + 0.25, 0)] 
data[, value:= ifelse(variable=="vl", 3 + exp(-4*M_visit_time), row/10 + 2)]
data[, M_agesero:= ifelse(variable=="vl", agesero, 0)]
data[, D_intercept:= ifelse(variable=="observed_survival", 1, 0)]
data[, D_agesero:= ifelse(variable=="observed_survival", agesero, 0)]
data[, row:=NULL]

example_formula <- "value~ModelGradient(time=M_visit_time,b0,b2,b3)~M_agesero + D_intercept + D_agesero + (b0|patient_id)"

#this works, outside of a function:
Model<- ~b0+b2*exp(-b3*time)
ModelGradient<-deriv(Model,namevec=c("b0","b2","b3"),
               function.arg=c("time","b0","b2","b3"))

out<-nlmer(as.formula(example_formula), data=data,
           start = c(b0=3,b2=1,b3=4),
           control=nlmerControl(optimizer="bobyqa", optCtrl=list(maxfun=200000)))

#but when I write a function:
run_nonlin<- function(model_formula, data){
            Model<- ~b0+b2*exp(-b3*time)
            ModelGradient<-deriv(Model,namevec=c("b0","b2","b3"),
                           function.arg=c("time","b0","b2","b3"))

          print(paste("hello I am the model formula and I exist in this namespace! I am:",
         model_formula))
         out<-nlmer(as.formula(model_formula), data=data,
                 start = c(b0=3,b2=1,b3=4),
                 control=nlmerControl(optimizer="bobyqa",
                  optCtrl=list(maxfun=200000)))
           return(out)
}

#and call:
function_output <- run_nonlin(model_formula=example_formula, data=data)

# I get the error: 
# Error in as.formula(model_formula) : object 'model_formula' not found

      

As a side note, I did something very similar to this, no problem.

Any advice would be greatly appreciated.

(edited to include error message)

+3


source to share


1 answer


Seems to nlmer

have a weird way of parsing the formula you are passing to the function. You apparently cannot pass a variable that is not defined in the global environment. This seems to be happening because it nlformula

calls as.formula

on an unvalued symbol that runs like in a formula. This means the lexical scope is used for character resolution, so it looks model_formula

in the namespace stats

and then the global environment, not the scope defined by your function.

A workaround would be to evaluate this parameter and then pass that value through do.call()

, for example



run_nonlin<- function(model_formula, data){
    Model<- ~b0+b2*exp(-b3*time)
    ModelGradient<-deriv(Model,namevec=c("b0","b2","b3"),
                       function.arg=c("time","b0","b2","b3"))

    out <- do.call('nlmer', list(as.formula(model_formula), 
        data=quote(data),
        start = c(b0=3,b2=1,b3=4),
        control=nlmerControl(optimizer="bobyqa",
        optCtrl=list(maxfun=200000))))

    return(out)
}

      

+3


source







All Articles