R写作风格 - 需要与::

时间:2010-12-06 23:49:24

标签: r namespaces packages

好的,我们都熟悉R中的双冒号运算符。每当我要写一些函数时,我都会使用require(<pkgname>),但我一直在考虑使用::。在自定义函数中使用requirelibrary更好,因为require会返回警告和FALSE,与library不同,如果您提供的是::,则返回错误不存在的包裹。

另一方面,require运算符从包中获取变量,而::加载整个包(至少我希望如此),因此速度差异首先出现在我的脑海中。 require必须快于read.systat

我做了一些分析以检查 - 我编写了两个简单的函数,分别从foreign包加载require函数,::Iris.syd因此导入foreign包裹的::数据集,每个复制函数1000次(这是无耻的任意),并且......打了一些数字。

奇怪(或不是)我发现用户CPU和经过时间方面存在显着差异,而系统CPU方面没有显着差异。然而更奇怪的结论是:::实际上更慢! ::的文档非常直言,只是通过查看来源,显然#!/usr/local/bin/r ## with require fn1 <- function() { require(foreign) read.systat("Iris.syd", to.data.frame=TRUE) } ## times n <- 1e3 sink("require.txt") print(t(replicate(n, system.time(fn1())))) sink() 应该表现得更好!

需要

#!/usr/local/bin/r

## with ::
fn2 <- function() {
  foreign::read.systat("Iris.syd", to.data.frame=TRUE)
}

## times
n <- 1e3


sink("double_colon.txt")
print(t(replicate(n, system.time(fn2()))))
sink()

双冒号

user CPU:     W = 475366    p-value = 0.04738  MRr =  975.866    MRc = 1025.134
system CPU:   W = 503312.5  p-value = 0.7305   MRr = 1003.8125   MRc =  997.1875
elapsed time: W = 403299.5  p-value < 2.2e-16  MRr =  903.7995   MRc = 1097.2005

抓取CSV数据here。一些统计数据:

require

MRr是::的平均排名,MRc是::的同上。我一定做错了。它没有任何意义...... require的执行时间似乎更快!!!我可能搞砸了,你不应该放弃那个选择......

好的......我浪费了我的时间,以便看到存在一些差异,我进行了完全无用的分析,所以,回到问题:

在编写函数时,为什么选择::优先于{{1}}?

=)

2 个答案:

答案 0 :(得分:12)

  

“为什么一个人更喜欢要求::   在写函数时?“

我通常更喜欢require,因为有很好的TRUE / FALSE返回值,这让我可以在进入代码之前处理包前不可用的可能性。尽可能早地崩溃而不是分析中途。

当我需要确保使用正确版本的函数时,我只使用::,而不是使用掩盖名称的其他软件包中的版本。

  

另一方面,:: operator得到   来自包的变量,而   需要加载整个包装(至少   我希望如此),所以速度差异来了   首先是我的想法。 ::必须更快   比要求。

我认为您可能忽略了foreign包根据the first page of its manual使用的延迟加载的影响。本质上,使用延迟加载的包会延迟对象(如函数)的加载,直到第一次调用对象为止。所以你的论点“::必须比要求更快”并不一定正确,因为foreign在用require附加时不会将所有内容加载到内存中。有关延迟加载的完整详细信息,请参阅RNews中的Prof. Ripley's article,第4卷,第2期。

答案 1 :(得分:6)

由于加载程序包的时间几乎总是很小,相比于你花在试图弄清楚你六个月前编写的代码的时间,在这种情况下编码的清晰度是最重要的。

对于脚本,在开始时拨打requirelibrary可让您立即知道需要哪些套餐。

同样,在函数开头调用require(或requirePackage中的Hmisctry_require中的ggplot2)包装是最明确的显示你需要使用该包的方式。

对于包之间存在命名冲突的情况,应保留

:: - 比较,例如,

Hmisc::is.discrete

plyr::is.discrete