【问题标题】:How to pass call object into do.call如何将调用对象传递给 do.call
【发布时间】:2023-02-24 10:51:03
【问题描述】:

给出一个分类函数ranger,我想使用formals从其定义中获取所有参数及其默认值。然后,我想更改一些默认值并将它们用作 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)

但它不起作用:

Error in as.logical(test) : 
  cannot coerce type 'closure' to vector of type 'logical'

sample.fraction 元素似乎是错误的原因。它是一个 call 对象。如果我使用以下方法删除该元素:

lParams[["sample.fraction"]]<-NULL

...所以,我的代码有效。

我不知道如何对待这个对象来防止这个错误。任何想法? 谢谢!!

【问题讨论】:

  • 我不确定您为什么要提取所有形式参数只是为了更改默认值。如果缺少默认值,将使用默认值,因此您只需要包含您实际想要更改的参数。从您的代码中仅使用 do.call("ranger", list(data = quote(iris), formula = Species ~ .)) 就足够了。

标签: r classification do.call


【解决方案1】:

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)

默认惰性参数值有点特殊。没有任何东西可以传递给他们,如果您缺少该值,它们将表现得像。这是因为您传入的值是在与默认参数不同的环境中计算的。您得到的特定错误“无法将类型‘闭包’强制转换为‘逻辑’类型的向量”是因为replace 是全局环境中的函数,但在函数本身中具有不同的含义。

如果您想避免潜在的问题,最好不要从所有形式论证开始。或者在列表中过滤掉任何调用或符号。你可以过滤掉它们

lParams <- lParams[!sapply(lParams, function(x) any(c("call","symbol") %in% class(x)))]

【讨论】:

    猜你喜欢
    • 2015-12-16
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 2016-09-03
    • 2020-10-09
    • 2012-02-23
    相关资源
    最近更新 更多