将包和函数称为另一个函数中的参数

时间:2019-10-18 14:24:22

标签: r function

我试图在R中的不同程序包中查找特定功能的方法。例如,methods(broom::tidy)将返回程序包tidy中功能broom的所有方法。对于我当前的问题,最好将methods函数放在另一个函数中,如下所示: f1 <- function(x,y){ methods(x::y) }

(我删除了与问题无关的其他代码部分。) 但是,当我运行这样的函数时:

f1 <- function(x,y){ methods(x::y)}
f1(broom,tidy)

我收到错误

  

loadNamespace(name)中的错误:没有名为“ x”的包

如果我尝试将其修改为仅更改功能但将软件包保持不变,则会收到类似错误:

f2 <- function(y){  methods(broom::y)}
f2(tidy)
  

错误:“ y”不是从“ namespace:broom”导出的对象

如何获取包和函数名称以在函数中正确评估?当前的问题是否与r试图评估/替代函数中的值有关?

1 个答案:

答案 0 :(得分:5)

::methods()函数都使用非标准评估才能工作。这意味着您需要更加聪明地将值传递给函数,以使其正常工作。这是一种方法

f1 <- function(x,y){ 
  do.call("methods", list(substitute(x::y)))
}
f1(broom,tidy)

在这里,我们使用substitute()进行扩展,并将xy的值传递到名称空间查找中。这样可以解决您可以看到的::部分

f2 <- function(x,y){ 
  substitute(x::y)
}
f2(broom,tidy)
# broom::tidy

我们需要替换项​​,因为很可能会有一个带有功能x的软件包y。因此,使用::时不会扩展变量。请注意,如果您另外需要使用字符值从名称空间中提取值,则::只是getExportedValue()的包装。

但是还有另外一个陷阱:methods()不评估其参数,它使用原始表达式来找到方法。这意味着我们实际上不需要broom::tidy的值,我们可以传递该文字表达式。由于我们需要评估替代项以获得所需的表达式,因此我们需要使用do.call()构建调用以评估substitute并将该表达式传递给methods()