Search code examples
rfunctionassign

R Function - assign LMER to dynamic variable name


To create a more compact script, I am trying to create my first function.

The general function is:

    f.mean <- function(var, fig, datafile){
      require(lme4)
      change <- as.symbol(paste("change", var, sep=""))
      base <- as.symbol(paste("baseline", var, sep = ""))
      x <- substitute(lmer(change ~ base + (1|ID),  data=datafile))
      out<-eval(x)
      name <- paste(fig,".", var, sep="")
      as.symbol(name) <- out
      }
}

The purpose of this function is to input var, fig and datafile and to output a new variable named fig.var containing out (eval of LMER).

Apparently it is difficult to 'change' the variable name on the left side of the <-.

What we have tried so far:

 - assign(name, out) 
 - as.symbol(name) <<- out
 - makeActive Binding("y",function() x, .GlobalEnv)
 - several rename options to rename out to the specified var name

Can someone help me to assign the out value to this 'run' specific variable name? All other suggestions are welcome as well.


Solution

  • As @Roland comments, in R (or any) programming one should avoid indirect environment manipulators such as assign, attach, list2env, <<-, and others which are difficult to debug and break the flow of usual programming involving explicitly defined objects and methods.

    Additionally, avoid flooding your global environment of potentially hundreds or thousands of similarly structured objects that may require environment mining such as ls, mget, or eapply. Simply, use one large container like a list of named elements which is more manageable and makes code more maintainable.

    Specifically, be direct in assigning objects and pass string literals (var, fig) or objects (datafile) as function parameters and have function return values. And for many inputs, build lists with lapply or Map (wrapper to mapply) to retain needed objects. Consider below adjustment that builds a formula from string literals and passes into your model with results to be returned at end.

    f.mean <- function(var, fig, datafile){
      require(lme4)
      myformula <- as.formula(paste0("change", var, " ~ baseline", var, " + (1|ID)"))
    
      x <- lmer(myformula, data=datafile)
      return(x)
    }
    
    var_list <- # ... list/vector of var character literals
    fig_list <- # ... list/vector of fig character literals
    
    # BUILD AND NAME LIST OF LMER OUTPUTS  
    lmer_list <- setNames(Map(f.mean, var_list, fig_list, MorArgs=df),
                          paste0(fig_list, ".", var_list))
    
    # IDENTIFY NEEDED var*fig* BY ELEMENT NAME OF LARGER CONTAINER
    lmer_list$fig1.var1
    lmer_list$fig2.var2
    lmer_list$fig3.var3