来自[package] import [function] in R

时间:2017-07-17 18:06:47

标签: r function namespaces encapsulation

使用Python或R中的数据,我们经常加载几个包。在某些情况下,两个包(例如foobar)可能都包含某些功能(例如do_stuff)。

在Python中管理它以防止歧义或意外的方式如下:

from foo import do_stuff
from bar import other_function    # (does not load/import do_stuff() from bar)

在R中,我看到的所有代码都只导入整个包 多个library(package_name)语句。我认为这会导致非常难以捕获的错误。例如,请参阅Reordering factor gives different results, depending on which packages are loaded。事实上,即使"没有掩盖,也会发生这种情况,因为reorder.factor不存在于base。"

我希望这个问题的一般答案与上面的from package import function代码类似,但它不是。事实上,公认的(也是唯一的)答案只能解释为什么存在这个问题(而不是淡化这种贡献)。答案的评论中提供了一种解决方法,但该解决方法特定于该特定功能(reorder)。

我是否可以从R中的特定包中仅导入特定功能?因此,我可以有意识地明确我的代码中所有函数调用的来源,并确保他们按照我认为他们正在做的事情进行操作?

4 个答案:

答案 0 :(得分:6)

您可以使用package::function()构造明确告诉R哪个包应该用于给定函数。您甚至可以使用它来从未加载library的包中调用函数。

library(dplyr) # Has a function called filter()
library(plyr) # Also has a filter() function

dplyr::filter(foo)
plyr::filter(bar)

如果您想确保最大限度地减少代码混淆的可能性,我强烈推荐使用conflicted包,这会强制您明确识别所有不明确函数调用的包:{{3} }

答案 1 :(得分:2)

您正在比较两种功能不同的语言。首先,您可以使用::轻松地从包中引用函数,例如:

fortunes::fortune()

fortune包中调用fortunes功能。

但你也必须小心这样做。因为取决于包的构造方式,最终可能会使用依赖于命名空间中的其他(非导出)函数的函数,但由于未加载命名空间,因此无法找到该函数。我自己使用来自例如mgcv包的绘图函数来解决这个问题。这是使用library()附加包的一个原因,正如Andrew Breza在他的回答中所说明的那样。至少使用::构造调用的函数将按预期工作(99.9%)。

但是你链接到的问题不会被解决。问题是“糟糕的设计”,包装作者认为他需要一种S3方法来重新排序因子而不是特定于他的包的类。这样做为整个因子类注册了一个S3方法,因此改变了在因子上调用reorder()的每个函数的行为。

由于这个问题是由软件包开发人员自己引起的,除了自己黑客入侵S3系统以找到所需的实际方法之外,你几乎无法做到这一点。

答案 2 :(得分:2)

尽管this答案是正确的,但不适用于诸如magrittr的{​​{1}}和%>%之类的中缀运算符。 %$%程序包可享受待遇:

import

但是显然可以用于任何功能:

import::from(magrittr, "%$%")

请注意,“ [[import::from(foo, "do_stuff", "do_other_stuff") ]不适用于import。它的名称是为了使像library这样的调用具有表现力。”有关更多详细信息,请参见https://CRAN.R-project.org/package=import

答案 3 :(得分:1)

从 R 4.0 开始,您还可以使用主 library() 函数执行此操作:

library(dplyr, include.only = c("select", "mutate"))
library(dplyr, exclude = c("filter", "lag"))