WiggyStardust
WiggyStardust

Reputation: 182

Pass model formula as argument in R

I need to cross-validate several glmer models on the same data so I've made a function to do this (I'm not interested in preexisting functions for doing this). I want to pass an arbitrary glmer model to my function as the only argument. Sadly, I can't figure out how to do this, and the interwebz won't tell me.

Ideally, I would like to do something like:

model = glmer(y ~ x + (1|z), data = train_folds, family = "binomial"
model2 = glmer(y ~ x2 + (1|z), data = train_folds, family = "binomial"

And then call cross_validation_function(model) and cross_validation_function(model2). The training data within the function is called train_fold.

However, I suspect I need to pass the model formula in different way using reformulate.

Here is an example of my function. The project is about predicting autism(ASD) from behavioral features. The data variable is da.

library(pacman)
p_load(tidyverse, stringr, lmerTest, MuMIn, psych, corrgram, ModelMetrics, 
caret, boot)

cross_validation_function <- function(model){ 

  #creating folds  
  participants = unique(da$participant)
  folds <- createFolds(participants, 10)


  cross_val <- sapply(seq_along(folds), function(x) {

    train_folds = filter(da, !(as.numeric(participant) %in% folds[[x]]))
    predict_fold = filter(da, as.numeric(participant) %in% folds[[x]])

    #model to be tested should be passed as an argument here    
    train_model <-  model



    predict_fold <- predict_fold %>% 
      mutate(predictions_perc = predict(train_model, predict_fold, allow.new.levels = T),
             predictions_perc = inv.logit(predictions_perc),
             predictions = ifelse(predictions_perc > 0.5, "ASD","control"))

    conf_mat <- caret::confusionMatrix(data = predict_fold$predictions, reference = predict_fold$diagnosis, positive = "ASD") 

    accuracy <- conf_mat$overall[1]
    sensitivity <- conf_mat$byClass[1]
    specificity <- conf_mat$byClass[2]


    fixed_ef <- fixef(train_model) 

    output <- c(accuracy, sensitivity, specificity, fixed_ef)

    })

    cross_df <- t(cross_val)
    return(cross_df)
  }

Solution developed from the comment: Using as.formula strings can be converted into a formula which can passed as arguments to my function in the following way:

cross_validation_function <- function(model_formula){
...
train_model <- glmer(model_formula, data = da, family = "binomial") 
...}

formula <- as.formula( "y~ x + (1|z"))
cross_validation_function(formula)

Upvotes: 4

Views: 1963

Answers (1)

kangaroo_cliff
kangaroo_cliff

Reputation: 6222

If you aim is to extract the model formula from a fitted model, the you can use attributes(model)$call[[2]]. Then you can use this formula when fitting model with the cv folds.

   mod_formula <-  attributes(model)$call[[2]]
   train_model = glmer(mod_formula , data = train_data, 
                family = "binomial")

Upvotes: 1

Related Questions