在这种情况下应避免附着吗?

时间:2018-07-24 13:02:07

标签: r

尽管对此主题有一些疑问(例如this question),但都没有一个回答我的特定问题(据我所知)。

假设我有一个依赖于很多参数的函数。为了演示,我选择了3个参数:

myfun <- function(x1, x2, x3){
   some code containing x1, x2, x3
}

通常,输入参数已经包含在list中:

xlist <- list(x1 = 1, x2= 2, x3 = 3)

我想使用myfun中包含的输入来运行xlist,如下所示:

myfun(xlist$x1, xlist$x2, xlist$x3)

但是,这似乎太费力了(由于大量的参数)。

因此,我决定修改myfun:而不是所有输入参数。现在,它将整个列表作为一个输入输入:在代码的开头,我使用attach来使用与上面相同的代码。

myfun2 <- function(xlist){
  attach(xlist)
  same code as in myfun containing x1, x2, x3
  detach(xlist)
}

我认为这将是一个很好的解决方案,但是许多用户建议不要使用attach

您怎么看?有没有论点更喜欢myfun胜过myfun2

谢谢。

4 个答案:

答案 0 :(得分:4)

我认为您最好使用do.calldo.call将接受列表并将其转换为参数。

myfun <- function(x1, x2, x3){
  x1 + x2 + x3
}

xlist <- list(x1 = 1, x2= 2, x3 = 3)

do.call(myfun, xlist)

这样做的好处是明确说明参数的含义,这使得对代码进行推理,维护和调试变得更加容易。

比较棘手的地方是xlist中包含的值比函数所需的更多。例如,以下引发错误:

xlist <- list(x1 = 1, x2 = 2, x3 = 3, x4 = 4)

do.call(myfun, xlist)

您可以通过将参数与形式表达式匹配来规避这一点

do.call(myfun, xlist[names(xlist) %in% names(formals(myfun))])

仍然有点输入,但是如果您要谈论10个以上的参数,它仍然比xlist$x1, xlist$x2, xlist$x3等要容易得多。

LAP也提供了一种有用的解决方案,但最好将with用于通话之外。

with(xlist, myfun(x1, x2, x3))

答案 1 :(得分:0)

您可以只使用with()

xlist <- list(x1 = 1, x2= 2, x3 = 3)

FOO <- function(mylist){
  with(mylist,
       x1+x2+x3
  )
}

> FOO(xlist)
[1] 6

不过,我不相信这种方法。该功能将取决于列表中正确命名的元素。

答案 2 :(得分:0)

我的方法是这样的:

finishAffinity()

但是,您将需要知道函数中参数的名称。

也许do.call()函数可以在这里发挥作用。

testfun <- function (a_list)
{
  args = a_list
  print(args$x1)
  print(args$x2)
  print(args$x3)
}

my_list <- list(x1=2, x2=3, x3=4)

testfun(my_list)

答案 3 :(得分:0)

您可以将列表分配给函数的环境:

myfun <- function(xlist) {
  for (i in seq_along(xlist)) {
    assign(names(xlist)[i], xlist[[i]], envir = environment())
  }
# or if you dislike for-loops
# lapply(seq_along(xlist), function(i) assign(names(xlist)[i], xlist[[i]], envir = parent.env(environment())))
  print(paste0(x2, x3)) # do something with x2 and x3
  print(x1 * x3) # do something with x1 and x3
}
myfun(list(x1 = 4, x2 = "dc", x3 = c(3,45,21)))