Search code examples
rparametersclassification

R use the name of function as a parameter in formals


I am working with several classification algorithms from different libraries (for example):

library(ranger) #RandomForest
library(gbm) #Gradient Boosting

I need to use formals function to get all the arguments from all of them.

The following attempts works perfectly:

formals(gbm)
formals(gbm::gbm)
formals("gbm")
        
functionName="gbm"
formals(functionName)

What I need is to parametrize the name of the package as well as the name of the function, but it fails. Something like this:

> packageName="gbm"
> functionName="gbm"
> formals(packageName::functionName)
Error in loadNamespace(x) : there is no package called ‘packageName’

Is there anyway to do it? Thanks


Solution

  • The good thing is that :: accepts strings:

    `::`("gbm", "gbm")
    

    The above code is working.

    However, when we use an object name in which the string is stored, :: takes this as literal expression and looks for a package called packageName.

    packageName <- functionName <- "gbm"
    `::`(packageName, functionName)
    #> Error in loadNamespace(x): there is no package called 'packageName'
    

    With base R we can use eval(bquote()) and evaluate the strings early with .().

    By evaluating the strings early with .() we make it clear that we are really looking for the string value (that is the value of packageName) and not the object name itself.

    formals(eval(bquote(`::`(.(packageName), .(functionName)))))
    
    #> $formula
    #> formula(data)
    #> 
    #> $distribution
    #> [1] "bernoulli"
    #> 
    #> $data
    #> list()
    #> 
    #> $weights
    #> 
    #> 
    #> $var.monotone
    #> NULL
    #> 
    #> $n.trees
    #> [1] 100
    #> 
    #> $interaction.depth
    #> [1] 1
    #> 
    #> $n.minobsinnode
    #> [1] 10
    #> 
    #> $shrinkage
    #> [1] 0.1
    #> 
    #> $bag.fraction
    #> [1] 0.5
    #> 
    #> $train.fraction
    #> [1] 1
    #> 
    #> $cv.folds
    #> [1] 0
    #> 
    #> $keep.data
    #> [1] TRUE
    #> 
    #> $verbose
    #> [1] FALSE
    #> 
    #> $class.stratify.cv
    #> NULL
    #> 
    #> $n.cores
    #> NULL
    

    With {rlang} we can use inject() and !! sym():

    library(rlang)
    formals(inject(`::`(!! sym(packageName), !! sym(functionName))))
    

    Of course in base R we always have the option to eval(parse()):

    packageName="gbm"
    functionName="gbm"
    
    formals(eval(str2lang(paste0(packageName, "::", functionName))))
    

    Created on 2023-02-19 with reprex v2.0.2