使用Python或R中的数据,我们经常加载几个包。在某些情况下,两个包(例如foo
和bar
)可能各自包含一些功能(例如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”,也会发生这种情况。
我预计这个问题的一般答案就像上面的from package import function
代码,但事实并非如此。事实上,公认的(也是唯一的)答案只能解释为什么存在这个问题(而不是淡化这种贡献)。答案的评论中提供了一种解决方法,但该解决方法特定于该特定功能(reorder
)。
有一般的方法我只能导入R中特定包的特定功能吗?因此,我可以有意识地明确我的代码中的所有函数调用来自何处,并确保它们执行我认为他们正在做的事情?
您可以使用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
包,这会强制你明确地识别所有模糊函数调用的包:https://www.tidyverse.org/articles/2018/06/conflicted/
您正在比较两种功能不同的语言。首先,您可以使用::
轻松地从包中引用函数,例如:
fortunes::fortune()
从fortune
包中调用fortunes
函数。
但你也必须小心这样做。因为取决于包的构造方式,最终可能会使用依赖于命名空间中的其他(非导出)函数的函数,但由于未加载命名空间,因此无法找到该函数。我自己使用例如mgcv
包的绘图函数来解决这个问题。这是使用library()
附加包裹的一个原因,正如Andrew Breza在他的回答中所说明的那样。至少使用::
构造调用的函数将按预期工作(99.9%的时间)。
但是你链接的问题不会被解决。问题是“糟糕的设计”,包装作者认为他需要一种S3方法来重新排序因子而不是特定于他的包的类。这样做为整个因子类注册了一个S3方法,因此改变了在一个因子上调用reorder()
的每个函数的行为。
由于这个问题是由软件包开发人员自己造成的,除了自己黑客入侵S3系统以找到所需的实际方法之外,你几乎无法做到这一点。
虽然this答案是正确的,但它对qixxswpoi的magrittr
和%>%
等中缀运算符不起作用。 %$%
套餐是一种享受:
import
但显然可以用于任何功能:
import::from(magrittr, "%$%")
请注意,“[import::from(foo, "do_stuff", "do_other_stuff")
]不适合与import
一起使用。它被命名为像library
表达的那样进行调用。”有关详细信息,请参阅import::from(pkg, fun1, fun2)
。