R中的“导入为”
Posted
技术标签:
【中文标题】R中的“导入为”【英文标题】:"import as" in R 【发布时间】:2014-08-14 23:43:08 【问题描述】:有没有办法在 R 中导入另一个名称的包,就像在 Python 中使用 import as
一样,例如import numpy as np
?我最近开始使用package::function
来避免Hmisc::summarize
和plyr::summarize
之间的冲突。
我希望能够分别写成h::summarize
和p::summarize
。这在 R 中可能吗?
【问题讨论】:
那是用来打包的吗? 不,我只是不想要腕管(expression()
是我最喜欢的新功能),我也不喜欢不可预测的错误。虽然最终我确实计划在包上工作,所以如果在这种情况下有单独的考虑,我想听听它们。
您是否真的遇到了经常需要这样做的冲突?还是只是几个包中的几个你最喜欢的功能?
这只是我不止一次遇到的问题。我也倾向于编写大量的掩码和包装函数供个人使用,有时会导致无法预料的冲突。
这些确实是您可能遇到的最可预测的错误。总结一下,您可以在 plyr 中使用 summarise
,在 Hmisc 中使用 summarize
。为自己保存三个或四个字符以避免明确地Hmisc::
'ing 是愚蠢的。更好的方法是使用expr<TAB>
填写其余部分,这也会向您显示它们所在的包。我会享受我的腕管并写几次package::function
。
【参考方案1】:
这不是你想要的,因为它涉及从::
表示法更改为$
表示法,但是如果你加载一个包命名空间(不附加它),你可以通过它的环境名称来引用它:
h <- loadNamespace('Hmisc')
p <- loadNamespace('plyr')
> summarize(iris$Sepal.Length, iris$Species, FUN=mean)
Error: could not find function "summarize"
> Hmisc::summarize(iris$Sepal.Length, iris$Species, FUN=mean)
iris$Species iris$Sepal.Length
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588
> h$summarize(iris$Sepal.Length, iris$Species, FUN=mean)
iris$Species iris$Sepal.Length
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588
> summarise(iris, x = mean(Sepal.Length))
Error: could not find function "summarise"
> plyr::summarise(iris, x = mean(Sepal.Length))
x
1 5.843333
> p$summarise(iris, x = mean(Sepal.Length))
x
1 5.843333
但是请注意,您确实无法使用标准的 ?
表示法访问文档文件(例如,? p$summarise
不起作用)。因此,它可以很好地为您提供速记,但可能不适合交互式使用,因为您仍然必须求助于? plyr::summarise
。
另请注意,您无权访问使用此方法存储在包中的数据对象。
【讨论】:
这似乎无法通过 $ 运算符提供包数据。 @jciloa 如果您正在寻找一种也适用于包数据的统一方法,the dev version of ‘box’ now supports this。【参考方案2】:这是一个只能用于交互模式的解决方案。您修改::
使其可以接受字符包名称,然后编写一个函数来注册别名。
`::` <- function(pkg, name)
sym <- as.character(substitute(pkg))
pkg <- tryCatch(get(sym, envir=.GlobalEnv), error=function(e) sym)
name <- as.character(substitute(name))
getExportedValue(pkg, name)
pkg.alias <- function(alias, package)
assign(alias, package, .GlobalEnv)
lockBinding(alias, .GlobalEnv)
pkg.alias('r', 'reshape2')
r::dcast
但您也可以重新定义 ::
以查找与您的缩写匹配的包,而不是使用别名:
`::` <- function(pkg, name)
pkg <- as.character(substitute(pkg))
pkg <- installed.packages()[grepl(paste0('^', pkg), installed.packages())]
name <- as.character(substitute(name))
getExportedValue(pkg, name)
ggp::ggplot
【讨论】:
这就是我要找的。也是substitute()
实际作用的一个很好的例子。
试图神奇地找出一个参数是否应该被评估是一个baaaaaaaad的想法。
@hadley 我已经更新了我的答案,因此它不能在函数内部使用。
为了从命令行使用,我希望输入::
后会显示包内容名称。不幸的是,他们没有出现。它适用于接受的答案。【参考方案3】:
与其给包起别名,不如直接给函数起别名?
hsumm <- Hmisc::summarize
dsumm <- dplyr::summarize
psumm <- plyr::summarize
我从eval(parse())
路径开始,但遇到了麻烦,需要重新开始工作。 @Thomas 的回答似乎以更流畅的方式得到了类似的结果,但这是无效的草案。
package_alias <- function(package, alias, infix = "..")
funs <- ls(paste0("package:", package))
for (i in seq_along(funs))
assign(paste0(alias, infix, funs[i]),
value = eval(parse(text = funs[i])), envir = .GlobalEnv)
你可以做类似的事情
package_alias("plyr", "p")
创建p..ddply
等
【讨论】:
因为我不想。请参阅我对另一个答案的评论;它仍然不是一个强大的通用解决方案。也就是说,我不是在寻找解决方法。 如果你错过了函数调用中的标点符号,你可以使用h..suummarize <- Hmisc::summarize
;)
我只想说我回到了这个问题,我比第一次看到它时更喜欢这个答案。 +1 实用性。【参考方案4】:
使用namespace 包生成另一个命名空间,别名为您感兴趣的命名空间。
library(namespace)
registerNamespace('ggp', loadNamespace('ggplot2'))
data(iris)
ggp::ggplot(iris, ggp::aes(x = Petal.Length, y = Sepal.Length)) + ggp::geom_point()
请注意,这样做的缺点是使包版本控制/安装要求对脚本更加不透明。
【讨论】:
不错!import_as <- function(pkg, alias) invisible(namespace::registerNamespace(alias, loadNamespace(pkg)))
【参考方案5】:
太长,无法很好地放在评论框中,所以伪答案:
如果它只有几个(或几十个)函数,那么覆盖包装函数怎么样,例如
summarize<-function(whichone='h',//all variables for either "summarize"// )
switch(whichone,
'h' = Hmisc::summarize(//all the appropriate variables//),
'p' = plyr:: summarize(//all the appropriate variables//)
)
【讨论】:
谢谢,但我想这个问题的重点是绕过你必须知道哪些功能冲突的部分。我知道您可以使用conflicts
,但这可能会令人讨厌,并且不会导致代码健壮(防止 future 重叠)。仅供参考,这就是 ...
参数非常方便的地方。【参考方案6】:
我希望能够分别编写 h::summarize 和 p::summarize。这在 R 中可能吗?
你可以使用‘box’:
box::use(
h = Hmisc,
p = plyr,
)
h$summarize(…)
p$summarize(…)
但box::use
提供的灵活性远不止于此。它是您所有代码重用需求的一站式商店。例如,您还可以决定从一个包中导入所有名称并重命名其中的一些符号;例如:
box::use(
h = Hmisc,
plyr[..., p_summarize = summarize],
)
这允许您使用“Hmisc”名称,方法是像以前一样在它们前面加上 h$
,并且所有来自“plyr”的名称不在它们前面加上任何前缀(它们是附加的);除了plyr::summarize
,它已附加在别名p_summarize
下。
此外,请注意,与library
不同,附加发生在本地。例如,您可以在函数中使用上述box::use
声明。然后,“plyr”仅“附加”在函数内部。在函数之外,代码不受影响。
【讨论】:
以上是关于R中的“导入为”的主要内容,如果未能解决你的问题,请参考以下文章