【问题标题】:Handling missing arguments, handled with missing(), to call a function inside a function处理丢失的参数,用missing()处理,在函数内部调用函数
【发布时间】:2021-01-17 05:09:41
【问题描述】:

我在函数myFunction() 中使用rpart()rpart() 接受几个使用missing() 函数处理的参数:

rpart(formula, data, weights, subset, na.action = na.rpart, method, model = FALSE, x = FALSE, y = TRUE, parms, control, cost, ...)

例如,参数method 可以不指定,并使用以下代码在rpart() 内部处理:

if (missing(method)) method <- "whatever default"

如何以最简单有效的方式将参数method 作为myFunction() 的参数传递,以便它处理默认的缺失参数?

如果我做类似的事情 myFunction(foo = 0, method){# somecode; rpart(y ~ x, data = data, method = method)} 那么这会引发错误,

缺少参数“方法”,没有默认值

我也尝试过使用rlang::missing() 之类的功能,但没有任何成功。

当然,一个选项是做一些事情,比如传递myFunction(method = NULL),然后使用 if-else 语句来传递或不传递这个参数,但是我必须对每种可能性进行编码(对于 4 个参数,即 16 个调用)和很笨拙。

请注意,我还想避免使用省略号,因为我想专门命名我的论点。


最小的可重复示例:

y <- c(0,0.1,0.1,-0.1, 100, 101, 99)
x <- c(1,2,3,4, 100,101,102)

myFunction <- function(x, y,
                       method,
                       weights,
                       subset,
                       parms){
      rpart(formula = y ~ .,
            data = data.frame(y, x),
            weights = weights,
            subset = subset,
            parms = parms)
}

myFunction(x,y)

eval(extras, data, env) 中的错误:缺少参数“权重”, 没有默认值

【问题讨论】:

  • 我试过这个例子f &lt;- function(x){if (missing(x)) x &lt;- "default";x};g &lt;- function(x){f(x = x)},但我没有错误。
  • @MrFlick 我已经更新了错误消息。如果我指定一个参数,我可以传递一个参数,但我希望能够保留默认(缺失)参数。 IE。未在 myFunction() 中指定 method 应该与未在 rpart() 中指定它一样工作
  • 我认为您在描述 ... 的用途。 myFunction(foo = 0, ...) {# somecode; rpart(y ~ x, data = data, ...)}?
  • 好吧,这里的错误消息谈到了“权重”,但您的示例中似乎没有使用。缺少的参数通常会正确传递,例如f1 &lt;- function(x) {print(missing(x))}; f2 &lt;- function(x) {f1(x)}; f2()。那里没有错误。所以目前还不清楚你在做什么会导致错误。一个可重现的例子是我们可以复制/粘贴到 R 中运行和测试。
  • @MrFlick 权重的东西在粘贴到这里时是一个错字。

标签: r


【解决方案1】:

这是使用match.call 的解决方案。这种模式在基本 R 函数中很常见。

考虑以下我们可能在包中找到的带有可选参数的函数:

package_fun <- function(x, method1, method2, method3)
{
  if(missing(method1)) method1 <- "Unspecified"
  if(missing(method2)) method2 <- "Unspecified"
  if(missing(method3)) method3 <- "Unspecified"
  data.frame(x, method1, method2, method3)
}

在我们自己的函数中,我们可以调用package_fun 来交换我们自己的可选参数,换出我们不想传递的任何参数,并添加我们选择的任何其他参数。我们只需要对package_fun 进行一次调用,无需担心组合爆炸:

myFunction <- function(foo = 0, method1, method2, method3)
{
  mc <- match.call()
  mc[[1]] <- quote(package_fun)
  mc <- mc[-which(names(mc) == "foo")]
  mc$x <- foo
  eval(mc, env = parent.frame())
}

所以现在我们可以这样做了:

myFunction(foo = 1, method1 = "Specified", method3 = "Specified")
#>   x   method1     method2   method3
#> 1 1 Specified Unspecified Specified

从您的可重现示例的角度来看,这看起来像:

myFunction <- function(x, y,
                       method,
                       weights,
                       subset,
                       parms){
  mc <- match.call()
  mc[[1]] <- quote(rpart)
  mc$formula <- y ~ .
  mc$data <- data.frame(y, x)
  mc$x <- NULL
  mc$y <- NULL
  eval(mc, envir =parent.frame())
}

所以我们会:

myFunction(x,y)
#> n= 7 
#> 
#> node), split, n, deviance, yval
#>       * denotes terminal node
#> 
#> 1) root 7 17136.31 42.87143 *

【讨论】:

  • 我还会添加 myFunction() 语句,例如 if (!missing(method)) mc$method &lt;- method(其余参数相同),对吧?
  • @D1X 不,你不需要。他们已经在通话中了。检查我的第一个例子。非缺失的method1method2 无需您执行任何操作即可通过。第一个包函数处理丢失的参数 - 这就像 rpart 处理丢失的参数。如果 rpart 已经处理了缺少的参数,则您的函数不需要这样做
  • 有趣的是,rpart 使用这种方法(请参阅其中的第一个 else)并且它会导致问题(因为 weight 被传递给 model.frame 而在顶层调用rpart 这不会发生)。
  • 是的,我明白了!谢谢!您能否详细说明envir = parent.frame() 的作用?我将在 future_lapply() 循环中使用调用 eval(mc, envir = parent.frame()),但它找不到函数 rpart()
  • @Roland 是的,有一些函数调用model.frame 是这样构建的,它不能很好地与*apply 类型函数配合使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-26
  • 2012-05-31
相关资源
最近更新 更多