Giving a classification function ranger
, I want to get all the parameters with their default values from its definition using formals
. Then, I want to change some default values and use them as parameter with do.call
library(ranger)
# Getting all the parameters for "ranger" function with their default values
lParams<-formals(ranger)
lParams<-as.list(lParams)
# Replace some default values for testing purposes
lParams$formula<-as.formula("Species~.")
lParams$data<-substitute(iris)
lParams[["..."]]<-NULL
#lParams[["sample.fraction"]]<-NULL
do.call("ranger",lParams)
But it does not work:
Error in as.logical(test) :
cannot coerce type 'closure' to vector of type 'logical'
It seems sample.fraction
element is the cause of the error. It is a call
object. If I remove that element using:
lParams[["sample.fraction"]]<-NULL
...so, my code works.
I do not know how to treat this object to prevent this error.
do.call
is limited by the same restrictions you are when calling a function. By taking all the formals and readding them, you are essentially calling
ranger(formula = Species ~ ., data = iris, num.trees = 500,
mtry = NULL, importance = "none", write.forest = TRUE, probability = FALSE,
min.node.size = NULL, max.depth = NULL, replace = TRUE, sample.fraction = ifelse(replace,
1, 0.632), case.weights = NULL, class.weights = NULL,
splitrule = NULL, num.random.splits = 1, alpha = 0.5, minprop = 0.1,
split.select.weights = NULL, always.split.variables = NULL,
respect.unordered.factors = NULL, scale.permutation.importance = FALSE,
local.importance = FALSE, regularization.factor = 1, regularization.usedepth = FALSE,
keep.inbag = FALSE, inbag = NULL, holdout = FALSE, quantreg = FALSE,
oob.error = TRUE, num.threads = NULL, save.memory = FALSE,
verbose = TRUE, seed = NULL, dependent.variable.name = NULL,
status.variable.name = NULL, classification = NULL, x = NULL,
y = NULL)
And you get the exact same error if you run that. Let's create a simplified example
foo <- function(x, y=x+5) {
x*y
}
foo(5)
# [1] 50
If I tried the same trick, I would get
params <- as.list(formals(foo))
params$x <- 5
do.call("foo", params)
# Error in foo(x = 5, y = x + 5) : object 'x' not found
because I cannot call
foo(x =5, y=x+5)
Default lazy parameter values are kind of special. There's nothing you can pass to them that will behave like if you leave the value missing. That's because values you pass in are evaluated in a different environment than default parameters. The specific error you get " cannot coerce type 'closure' to vector of type 'logical'" is because replace
is a function in the global enviroment, but has a different meaning within the function itself.
If you want to avoid potential problems, it's probably best not to start with all the formal arguments. Or at the very list filter out any calls or symbols. You could filter them out with
lParams <- lParams[!sapply(lParams, function(x) any(c("call","symbol") %in% class(x)))]