Search code examples
rfunctionglobal-variables

Modifying functions and their names based on variables in global environment


Let's say I have a feature dataframe, f

f = data.frame(X1 = 1:10,
                X2 = 11:20,
                X3 = 21:30)

And an outcome vector, o

o = 1:10

Is there a way for me to create the following 3 functions based on f's variables -- i.e., glmfun_X1, glmfun_X2, glmfun_X3 -- without writing each one out? e.g., I would rather NOT write out:

glmfun_X1 = function(X, Y) {
  glmout = glm(Y ~ ., data = data.frame(X[,"X1"]))
  return(glmout)
}

glmfun_X2 = function(X, Y) {
  glmout = glm(Y ~ ., data = data.frame(X[,"X2"]))
  return(glmout)
}

glmfun_X3 = function(X, Y) {
  glmout = glm(Y ~ ., data = data.frame(X[,"X3"]))
  return(glmout)
}

I would need the functions to be stored in my global environment, so that the following works:

glmfun_X1(X = f, Y = o)
glmfun_X2(X = f, Y = o)
glmfun_X3(X = f, Y = o)

I tried something using a combination of: this post and this post

glmfun <- function(X, Y) {
  glmout = glm(Y ~ ., data = data.frame(X[,xname]))
  return(glmout)
}


for (i in colnames(f)) {
  assign(x = paste0("glmfun_", i),
         value = glmfun,
         envir = .GlobalEnv)
  body(paste0("glmfun_", i))[[2]][[3]][[3]][[2]][[4]] = i
}

glmfun_X1(X = f, Y = o)
glmfun_X2(X = f, Y = o)
glmfun_X3(X = f, Y = o)

However, this doesn't work because xname isn't able to be changed within each function to "X1", "X2", and "X3", respectively, using the body function and a for-loop (I tried lapply, as well, but thought a for-loop would provide a clearer illustration. I got the same error using lapply). Note that, individually, this does work:

i = "X1"
body(glmfun_X1)[[2]][[3]][[3]][[2]][[4]] = i # this works

Any help would be much appreciated!


Solution

  • Easiest solution would be to use a for-loop and a eval-parse routine.

    
    f = data.frame(X1 = 1:10,
                   X2 = 11:20,
                   X3 = 21:30)
    
    
    for (i in names(f)) {
      eval(parse(text=paste0("glmfun_",i,"<-function(X, Y) {glm(Y ~ .,data=data.frame(X[,'",i,"']))}")))
    }
    
    

    i removed the return statement to make it more concise.