2

I'm struggling with determining the syntax to compare the value of a variable that contains a function as part of a conditional statement.

I've written the following function:

cv_func <- function(df, method, target, nFolds=5, seedVal=100,  metrics_list=c("ACC","TPR","PRECISION","F1"), l=0.3, m=0.2, n=500, h='a', kernal='rbfdot', c=1, i=TRUE, f=TRUE, k=1, x=TRUE)
  {
  # create folds using the assigned values
  set.seed(seedVal)
  folds = createFolds(df[,target],nFolds)

  # lapply loop
  cv_results <- lapply(folds, function(x)
    { 
    # data preparation:
      test_target <- df[x,target]
      test_input <- df[x,-target]

      train_target <- df[-x,target]
      train_input <- df[-x,-target]

      if (method==MLP) {
        pred_model <- method(train_target~., data=train_input, l=l, m=m, n=n, h=h)
        }
      else if (method==ksvm) {
        pred_model <- method(train_target~., data=train_input, kernal=kernal, C=c)
        }
      else if (method==IBk) {
        pred_model <- method(train_target~., data=train_input, control = Weka_control(I=i, K=k, F=f, X=x))
        }
      else {
        pred_model <- method(train_target~., data=train_input)
        }

      pred_train <- predict(pred_model, train_input)
      return(mmetric(train_target, pred_train, metrics_list))
    })

  # convert a list to a data frame using as.data.frame and convert this data frame to a matrix before using rowSds()
  cv_results_m <- as.matrix(as.data.frame(cv_results))

  cv_mean<- as.matrix(rowMeans(cv_results_m))
  cv_sd <- as.matrix(rowSds(cv_results_m))
  colnames(cv_mean) <- "Mean"
  colnames(cv_sd) <- "Sd"

  # Combine and show cv_results and Means and Sds
  cv_all <- cbind(cv_results_m, cv_mean, cv_sd)
  kable(t(cv_all),digits=3)
  }

When I attempt to run the function with default parameters, I get an error:

cv_func(df=df, method=IBk, target=20)

Error: "Error in method == "MLP" : comparison (1) is possible only for atomic and list types"

Any thoughts on whether I can use a variable containing a function as part of a conditional in R?

Kris Clegg
  • 25
  • 4
  • See https://stackoverflow.com/questions/9638372/how-to-compare-functions – Marius Jul 26 '19 at 01:18
  • @Marius the identical() function is a solid option as well. Got it to work with both solutions. For sure adding 'identical()' to my R toolbox – Kris Clegg Jul 26 '19 at 05:38

1 Answers1

1

The issue is related to the argument type. It seems like a string is needed as input and as it is a function, we can get the value of the function with get wrapped around the string. It may be better to have a default method for the last else

cv_func <- function(df=df, target=20, nFolds=5, seedVal=100, method, metrics_list=c("ACC","TPR","PRECISION","F1"), l=0.3, m=0.2, n=500, h='a', kernal='rbfdot', c=1, i=TRUE, f=TRUE, k=1, x=TRUE)
  {
  # create folds using the assigned values
  set.seed(seedVal)
  folds = createFolds(df[,target],nFolds)

  # lapply loop
  cv_results <- lapply(folds, function(x)
    { 
    # data preparation:
      test_target <- df[x,target]
      test_input <- df[x,-target]

      train_target <- df[-x,target]
      train_input <- df[-x,-target]

      if (method=="MLP") {
        pred_model <- get(method)(train_target~., data=train_input, l=l, m=m, n=n, h=h)
        }
      else if (method=="ksvm") {
        pred_model <- get(method)(train_target~., data=train_input, kernal=kernal, C=c)
        }
      else if (method=="IBk") {
        pred_model <- get(method)(train_target~., data=train_input, control = Weka_control(I=i, K=k, F=f, X=x))
        }
      else {
        pred_model <- get(method)(train_target~., data=train_input)
        }

      pred_train <- predict(pred_model, train_input)
      return(mmetric(train_target, pred_train, metrics_list))
    })

  # convert a list to a data frame using as.data.frame and convert this data frame to a matrix before using rowSds()
  cv_results_m <- as.matrix(as.data.frame(cv_results))

  cv_mean<- as.matrix(rowMeans(cv_results_m))
  cv_sd <- as.matrix(rowSds(cv_results_m))
  colnames(cv_mean) <- "Mean"
  colnames(cv_sd) <- "Sd"

  # Combine and show cv_results and Means and Sds
  cv_all <- cbind(cv_results_m, cv_mean, cv_sd)
  kable(t(cv_all),digits=3)
  }

and then call the function as

cv_func(method="IBk", metrics_list=metrics_list)
akrun
  • 874,273
  • 37
  • 540
  • 662
  • ahh, ok I hadn't thought to use 'get(method)' in the function and then store the method value as a string. I'll try that when RStudio.cloud comes back online (it just started undergoing maintenance and that's where my project is currently). – Kris Clegg Jul 26 '19 at 01:15
  • @KrisClegg. You can try on a small example offline to check if it works – akrun Jul 26 '19 at 01:16
  • @KrisClegg. There are many ways thiss could be implemented though. Another option is creeating a object-oriented method dispatch – akrun Jul 26 '19 at 01:17