好的,我们都熟悉R中的双冒号运算符。每当我要写一些函数时,我都会使用require(<pkgname>)
,但我一直在考虑使用::
。在自定义函数中使用require
比library
更好,因为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}}?”
=)
答案 0 :(得分:12)
“为什么一个人更喜欢要求:: 在写函数时?“
我通常更喜欢require
,因为有很好的TRUE / FALSE返回值,这让我可以在进入代码之前处理包前不可用的可能性。尽可能早地崩溃而不是分析中途。
当我需要确保使用正确版本的函数时,我只使用::
,而不是使用掩盖名称的其他软件包中的版本。
另一方面,:: operator得到 来自包的变量,而 需要加载整个包装(至少 我希望如此),所以速度差异来了 首先是我的想法。 ::必须更快 比要求。
我认为您可能忽略了foreign
包根据the first page of its manual使用的延迟加载的影响。本质上,使用延迟加载的包会延迟对象(如函数)的加载,直到第一次调用对象为止。所以你的论点“::
必须比要求更快”并不一定正确,因为foreign
在用require
附加时不会将所有内容加载到内存中。有关延迟加载的完整详细信息,请参阅RNews中的Prof. Ripley's article,第4卷,第2期。
答案 1 :(得分:6)
由于加载程序包的时间几乎总是很小,相比于你花在试图弄清楚你六个月前编写的代码的时间,在这种情况下编码的清晰度是最重要的。
对于脚本,在开始时拨打require
或library
可让您立即知道需要哪些套餐。
同样,在函数开头调用require
(或requirePackage
中的Hmisc
或try_require
中的ggplot2
)包装是最明确的显示你需要使用该包的方式。
::
- 比较,例如,
Hmisc::is.discrete
和
plyr::is.discrete