【问题标题】:how to pass the "..." parameters in the parent function to its two children functions in r如何将父函数中的“...”参数传递给 r 中的两个子函数
【发布时间】:2014-09-09 16:26:48
【问题描述】:

我正在尝试将一组参数传递给一个函数。这个函数有两个子函数,它们是上述参数集的一部分。

在以下“简化”示例中 f_combined 是一个接受 ... 的函数 我想进行以下函数调用,以便将xx 传递给f_sqr 并将yy 传递给f_plus

f_combined(xx = 2, yy = 2)

但它会给我一个错误:

Error in f_sqr(...) : unused argument (yy = 2) 

有什么建议吗?

f_sqr <- function(xx =1){
  xx ^ 2
}

f_plus <- function(yy =1){
  yy + 1
}

f_combined <- function(...){
  f_sqr(...) + f_plus(...)
}

【问题讨论】:

  • 你不能把默认参数放在组合函数中而不是使用...吗?
  • 并非如此。对于一个简单的功能,是的,我们可以做到。但我真的在寻找一个更复杂的函数,它可能将许多函数与许多参数结合起来。想想像 ggplot() 这样的函数。

标签: r function


【解决方案1】:

您可以访问 ... 作为命名的成对列表或按顺序访问它 ..n

f_sqr <- function(xx =1){xx ^ 2}
f_plus <- function(yy =1){yy + 1}

f_combined <- function(...){
  print(f_sqr(list(...)$xx))
  print(f_plus(list(...)$yy))
  print(f_sqr(..1))
  print(f_plus(..2))
}
f_combined( yy = 1, xx = 10)

[1] 100 (element with name xx of the list ...)
[1] 2 (element with name yy of the list ...)
[1] 1 (the first argument in the list ...)
[1] 11 (the second argument in the list ...)

?"..."的输出

10.4 “...”论证

另一个常见的要求是允许一个函数传递 参数设置到另一个。例如,许多图形函数使用 函数 par() 和 plot() 等函数允许用户传递 par() 的图形参数以控制图形输出。 (看 par() 函数,有关 par() 函数的更多详细信息。)这可以 通过包含一个额外的参数来完成,字面意思是“...”, 函数,然后可以传递。给出了一个大纲示例 下面。

 fun1 <- function(data, data.frame, graph=TRUE, limit=20, ...) {
   [omitted statements]
   if (graph)
     par(pch="*", ...)
   [more omissions]
 } 

不太频繁地,函数需要引用“...”的组件。 表达式 list(...) 计算所有此类参数并 在命名列表中返回它们,而 ..1、..2 等对它们进行评估 一次,'..n' 返回第 n 个不匹配的参数。

【讨论】:

  • 如果省略两个参数之一,这将失败。例如f_combined(yy=1) 不会给出预期的结果。
  • @nico,既然OP在问如何使用...,这就是我对如何使用它的理解。这就对了。似乎 MrFlick 想出了一个更稳定的解决方案。
  • 那么,如果您需要同时指定两个参数并且不能使用默认值,那么使用... 有什么意义呢?老实说,我认为最简单的方法是拥有,正如我上面评论的那样,f_combined &lt;- function(xx=1, yy=2) 并拥有其他两个没有默认值的函数。
【解决方案2】:

或者,您可以查询函数的 formals() 以查看它所期望的命名参数并仅传递这些参数。如果“child”函数接受...,那么我们将传递所有参数。此方法不适用于位置参数。

f_combined <- function(..., .fns =list(f_sqr, f_plus), .reduce=`+`){
   dots <- list(...)
   Reduce(.reduce, lapply(.fns, function(f) {
       if ("..." %in% names(formals(f))) {
           do.call(f, dots)
       } else if ( any( names(dots) %in% names(formals(f)) ) ) {
           do.call(f, dots[names(formals(f))])
       } else {
           f()
       }
   }))
}

在这里,我将这两个函数设置为作为参数运行 (.fns=list(f_sqr, f_plus)),以便可以轻松更改它们或轻松添加更多函数。我还设置了一个参数,指定如何组合这些值,而不是求和它们 (.reduce='+')。但基本思想是找到最好的数学命名参数集并将它们传递下去。由于您的“子”函数的参数也具有默认值,因此当您不传递任何参数时它们也会运行。

以下是一些示例调用

f_combined()
# [1] 3
f_combined(xx=2)
# [1] 6
f_combined(yy=2)
# [1] 4
f_combined(xx = 2, yy = 2)
# [1] 7

【讨论】:

  • 感谢您的回答。这对我来说是非常有用的。我认为使用(当 f 的参数多于 ...)可能会有所改进:do.call(f, dots[intersect(names(dots), names(formals(f)))])
猜你喜欢
  • 2023-01-22
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 2019-03-29
  • 2012-06-07
  • 2018-08-05
  • 2013-11-30
相关资源
最近更新 更多