在R中隐藏个人功能

时间:2011-01-28 12:15:04

标签: r namespaces

我的.Rprofile中有一些便利功能,例如handy function for returning the size of objects in memory。有时我喜欢在不重新启动的情况下清理我的工作区,并使用rm(list=ls())执行此操作,删除所有用户创建的对象和我的自定义函数。我真的很想不吹嘘我的自定义功能。

解决这个问题的方法似乎是使用我的自定义函数创建一个包,以便我的函数最终在他们自己的命名空间中。这不是特别难,但有没有更简单的方法来确保自定义函数不被rm()杀死?

7 个答案:

答案 0 :(得分:35)

attachsys.source合并为源环境并附加该环境。这里我在文件my_fun.R中有两个函数:

foo <- function(x) {
    mean(x)
}

bar <- function(x) {
    sd(x)
}

在我加载这些功能之前,显然找不到它们:

> foo(1:10)
Error: could not find function "foo"
> bar(1:10)
Error: could not find function "bar"

创建一个环境并将文件输入其中:

> myEnv <- new.env()
> sys.source("my_fun.R", envir = myEnv)

仍未显示,因为我们没有附加任何内容

> foo(1:10)
Error: could not find function "foo"
> bar(1:10)
Error: could not find function "bar"

当我们这样做时,它们是可见的,并且因为我们已将环境的副本附加到搜索路径,所以这些功能仍然存在rm() - 编辑:

> attach(myEnv)
> foo(1:10)
[1] 5.5
> bar(1:10)
[1] 3.027650
> rm(list = ls())
> foo(1:10)
[1] 5.5

我仍然认为你自己的个人套餐会更好,但上述情况可能就足够了。请记住,搜索路径上的副本只是一个副本。如果函数相当稳定并且你没有编辑它们,那么上面的内容可能会有用,但如果你正在开发函数并修改它们,它可能比它的价值更麻烦。

第二个选项是将它们全部命名为.foo而不是foo,因为ls()除非设置了参数all = TRUE,否则不会返回这样命名的对象:

> .foo <- function(x) mean(x)
> ls()
character(0)
> ls(all = TRUE)
[1] ".foo"         ".Random.seed"

答案 1 :(得分:21)

以下是两种方式:

1)让每个函数名都以点开头。例如, .f代替f。除非您使用ls,否则ls(all.names = TRUE)将不会列出此类函数,因此它们不会传递给您的rm命令。

,或者

2)将此信息放入.Rprofile

attach(list(
   f = function(x) x, 
   g = function(x) x*x
), name = "MyFunctions")

这些功能将在您的搜索列表中显示为名为"MyFunctions"的组件,而不是在您的工作区中,它们几乎可以像在工作区中一样访问。 search()将显示您的搜索列表,ls("MyFunctions")将列出您附加的功能的名称。由于它们不在您的工作区中,因此您通常使用的rm命令不会删除它们。如果您确实要删除它们,请使用detach("MyFunctions")

答案 2 :(得分:10)

Gavin的答案很精彩,我只是赞成它。仅仅为了完整性,让我再折腾一下:

R> q("no")

接着是

M-x R

创建一个新会话---重新读取.Rprofile。简单,快速,便宜。

除此之外,私人套餐是我书中的方式。

答案 3 :(得分:3)

另一种选择:将函数保存在.RProfile内的单独文件中。您可以在闲暇时直接从R内重新获取内容。

答案 4 :(得分:2)

我发现在创建或调试函数时,我的R环境经常会被各种对象弄得乱七八糟。我想要一种在保留个人功能的同时有效保持环境免受这些对象影响的方法。

下面的简单功能是我的解决方案。它做了两件事: 1)删除所有不以大写字母开头的非功能对象 2)将环境保存为RData文件

(需要R.oo包)

cleanup=function(filename="C:/mymainR.RData"){  
library(R.oo)  
# create a dataframe listing all personal objects
everything=ll(envir=1)
#get the objects that are not functions
nonfunction=as.vector(everything[everything$data.class!="function",1])
#nonfunction objects that do not begin with a capital letter should be deleted
trash=nonfunction[grep('[[:lower:]]{1}',nonfunction)]
remove(list=trash,pos=1)
#save the R environment
save.image(filename)
print(paste("New, CLEAN R environment saved in",filename))
}

为了使用此功能,必须始终保留3条规则:
1)将所有数据保存在R外部 2)对于我希望永久保留的非功能对象,使用以大写字母开头的名称 3)必须使用rm。

手动删除过时的功能

显然,这不是每个人的通用解决方案......如果你不遵守规则#1和#2,可能会带来灾难性的后果。但它确实有很多优点:a)担心我的数据被清理干扰()让我遵守使用R作为处理器而不是数据库的规定,b)我的主R环境太小我可以备份为电子邮件附件,c)自动保存新功能(我不必手动管理个人功能列表)和d)保留对预先存在的功能的所有修改。当然最好的一个是最明显的优点......我不必花时间做ls()并查看对象来决定是否应该使用它们。

即使你不关心我的系统的细节,R.oo中的“ll”函数对于这种事情非常有用。它可用于实现适合您个人编程风格的任何清理规则集。

Patrick Mohr

答案 5 :(得分:0)

第n个快速且脏的选项是在使用lsf.str()时使用rm()来获取当前工作空间中的所有函数。 ...并让你按照自己的意愿命名功能。

pattern <- paste0('*',lsf.str(), '$', collapse = "|")
rm(list = ls()[-grep(pattern, ls())])

我同意,这可能不是最佳做法,但它可以完成工作! (无论如何我必须选择性地清理自己......)

答案 6 :(得分:0)

与Gavin的答案类似,以下内容加载了一个函数文件,但没有留下额外的环境对象:

if('my_namespace' %in% search()) detach('my_namespace'); source('my_functions.R', attach(NULL, name='my_namespace')) 

这将删除旧版本的命名空间(如果它已附加(对开发很有用),然后附加一个名为my_namespace的空新环境并将my_functions.R源添加到其中。如果您不删除旧版本,则会构建多个同名的附加环境。

如果您想查看已加载哪些功能,请查看

的输出
ls('my_namespace')

要卸载,请使用

detach('my_namespace')

这些附加功能(如包)不会被rm(list=ls())删除。