【问题标题】:R: Using the MoreArgs argument in the apply family of functionsR:在应用函数族中使用 MoreArgs 参数
【发布时间】:2017-05-03 10:41:32
【问题描述】:

我有一个复杂的函数,它需要一堆图形对象和 ggplot 地图并将它们组合成 gtables。出于这个问题的目的,我将该函数表示为一个简单的线性函数,MyFun1 或 MyFun2,它们的区别仅在于存在 ... 参数。

创建 gtables 的函数有两个变化的参数和一堆在给定运行中不变的其他参数。我正在尝试使用 mapply 运行该函数,使用 MoreArgs 参数来提供常量(对于每次运行 - 在更大的循环中更改)参数。但是,我收到一个错误,说传递的值是多余的,尽管它们在正文中使用。

mArgs  <- list(y1=1, y2=2)
MyFun1  <- function(x, y){x*y1 + y*y2}
MyFun2 <- function(x, y, ...){x*y1 + y*y2}

R1 <- function(A, B){
   out <- mapply(MyFun, x=A, y=B, MoreArgs = mArgs)
} 
R1(1:3, 4:6)
 Error in (function (x, y)  : unused arguments (y1 = 1, y2 = 2)

追溯:

3. (function (x, y) 
{
    x * y1 + y * y2
})(x = dots[[1L]][[1L]], y = dots[[2L]][[1L]], y1 = 1, y2 = 2) 
2. mapply(MyFun, x = A, y = B, MoreArgs = mArgs) 
1. R1(1:3, 4:6) 

我认为问题可能在于 MyFun1 缺少必要的形式来将附加参数传递到正文中,所以我尝试添加一个 ... 参数。但现在 MyFun 无法在 MoreArgs 列表中找到参数。

R2 <- function(A, B){
   out <- mapply(MyFun2, x=A, y=B, MoreArgs = mArgs)
}
R2(1:3, 4:6)
 Error in (function (x, y, ...)  : object 'y1' not found 

追溯:

3. (function (x, y, ...) 
{
    x * y1 + y * y2
})(x = dots[[1L]][[1L]], y = dots[[2L]][[1L]], y1 = 1, y2 = 2) 
2. mapply(MyFun2, x = A, y = B, MoreArgs = mArgs) 
1. R2(1:3, 4:6) 

然后我想,也许全球环境中的 mArgs 不在 MyFun2 的范围内,虽然它似乎应该,以我有限的理解。所以我将它添加为每个调用函数的参数。这并没有改变结果。

R3 <- function(A, B, mArgs){
   out <- mapply(function(x,y, ...){x*y1 + y*y2}, x=A, y=B,
                 MoreArgs = mArgs)
}
R3(1:3, 4:6, mArgs)
 Error in (function (x, y, ...)  : object 'y1' not found

追溯:

3. (function (x, y, ...) 
{
    x * y1 + y * y2
})(x = dots[[1L]][[1L]], y = dots[[2L]][[1L]], y1 = 1, y2 = 2) 
2. mapply(function(x, y, ...) {
    x * y1 + y * y2
}, x = A, y = B, MoreArgs = mArgs) 
1. R3(1:3, 4:6, mArgs) 

我尝试在每个函数中用列表本身替换 mArgs,但在任何情况下都没有改变结果。

我很困惑。救命!

【问题讨论】:

  • 如何在函数 def MyFun2 &lt;- function(x, y, y1, y2){x*y1 + y*y2} 中显式编码额外的变量名称?
  • @mt1022 这行得通,如果你把它作为答案,我会接受。但我希望我知道为什么我不能让它与 MoreArgs 论点一起工作。我写了很多我理解的无​​缘无故不起作用的 R 代码。这很令人沮丧。

标签: r debugging scope arguments parameter-passing


【解决方案1】:

要解决您的问题,您可以这样做:

MyFun2 <- function(x, y, y1, y2){x*y1 + y*y2}

要回答为什么您的方法不起作用,请参阅dot-dot-dot 上的 R-lang:

2.1.9 点-点-点

“...”对象类型存储为一种配对列表类型。组件 '...' 可以从 C 代码中以通常的配对列表方式访问,但是 在解释代码中不容易作为对象访问。物体 可以捕获为列表,因此例如在表一中看到

args <- list(...)

....

for (a in args) {

如果函数将“...”作为形式参数,则任何与形式参数不匹配的实际参数都将与“...”匹配。

所以你必须手动从... 中提取y1y2

MyFun2 <- function(x, y, ...){
    additional.args <- list(...)
    y1 <- additional.args[[1]] 
    y2 <- additional.args[[2]]
    x*y1 + y*y2
}

MyFun2(1, 2, 1, 2)
# [1] 5

关于 moreArgs,它用于不会被矢量化的参数。看下面的例子:

mapply(function(x, y){
    print('----------------')
    print(x)
    print(y)
    x + y
}, x = 1:3, y = 1:3)

# [1] "----------------"
# [1] 1
# [1] 1
# [1] "----------------"
# [1] 2
# [1] 2
# [1] "----------------"
# [1] 3
# [1] 3
# [1] 2 4 6

mapply(function(x, y){
    print('----------------')
    print(x)
    print(y)
    x + y
}, x = 1:3, MoreArgs = list(y = 1:3))

# [1] "----------------"
# [1] 1
# [1] 1 2 3
# [1] "----------------"
# [1] 2
# [1] 1 2 3
# [1] "----------------"
# [1] 3
# [1] 1 2 3

#      [,1] [,2] [,3]
# [1,]    2    3    4
# [2,]    3    4    5
# [3,]    4    5    6

【讨论】:

  • 感谢这些非常明确的回答。我明白为什么你的两个答案都有效,为什么我的没有。但这是有代价的——我现在不明白 MoreArgs 是干什么用的。我认为重点或至少一点是封装一组参数并将它们完整地传递到列表中。但是如果你需要使用省略号让你的函数知道接下来会发生什么,然后从 ... 中显式提取每个参数,这比将每个参数写入函数更麻烦。我不指望你能解决这个问题,但如果有人愿意教书,我会很高兴知道。
  • @andrewH,moreArgs 用于不会被矢量化的参数,请参阅我的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-18
  • 2020-06-12
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
相关资源
最近更新 更多