英文:
How to pass call object into do.call
问题
给定一个分类函数 ranger
,我想从其定义中使用 formals
获取所有参数及其默认值。然后,我想更改一些默认值,并将它们作为参数使用 do.call
。
library(ranger)
# 获取 "ranger" 函数的所有参数及其默认值
lParams <- formals(ranger)
lParams <- as.list(lParams)
# 替换一些默认值以进行测试
lParams$formula <- as.formula("Species~.")
lParams$data <- substitute(iris)
lParams[[...]] <- NULL
#lParams[["sample.fraction"]] <- NULL
do.call("ranger", lParams)
但是它不起作用:
Error in as.logical(test) :
cannot coerce type 'closure' to vector of type 'logical'
似乎 sample.fraction
元素是错误的原因。它是一个 call
对象。如果我使用以下方法删除该元素:
lParams[["sample.fraction"]] <- NULL
...那么我的代码就可以工作了。
我不知道如何处理这个对象以防止出现此错误。
英文:
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.
答案1
得分: 4
do.call
受到与调用函数时相同的限制。通过获取所有形式参数并重新添加它们,本质上就是在调用以下函数:
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)
如果你运行上述代码,会得到完全相同的错误。让我们创建一个简化的示例:
foo <- function(x, y=x+5) {
x*y
}
foo(5)
# [1] 50
如果我尝试相同的技巧,我会得到以下错误:
params <- as.list(formals(foo))
params$x <- 5
do.call("foo", params)
# Error in foo(x = 5, y = x + 5) : object 'x' not found
因为我不能调用以下方式:
foo(x = 5, y = x + 5)
默认的延迟参数值有点特殊。你无法传递任何值给它们,使其表现得像你留下了该值。这是因为你传递的值在不同的环境中进行求值,而不同于默认参数。你得到的特定错误消息" cannot coerce type 'closure' to vector of type 'logical'"是因为 replace
在全局环境中是一个函数,但在函数内部具有不同的含义。
如果你想避免潜在问题,最好不要以所有形式参数开始。或者至少过滤掉任何调用或符号。你可以使用以下方式进行过滤:
lParams <- lParams[!sapply(lParams, function(x) any(c("call","symbol") %in% class(x)))]
英文:
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)))]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论