Скрытие личных функций в R
У меня есть несколько удобных функций в моем .Rprofile, таком как удобная функция для возврата размера объектов в память. Иногда мне нравится очищать рабочее пространство без перезагрузки, и я делаю это с помощью rm(list=ls())
, который удаляет все мои созданные пользователем объекты и мои пользовательские функции. Я бы очень хотел не взорвать свои пользовательские функции.
Похоже, что это создает пакет с моими пользовательскими функциями, чтобы мои функции попадали в собственное пространство имен. Это не особенно сложно, но есть ли более простой способ гарантировать, что пользовательские функции не будут убиты rm()?
Ответы
Ответ 1
Объедините attach
и sys.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()
-ed:
> 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"
Ответ 2
Вот два способа:
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")
.
Ответ 3
Ответ Гэвина замечательный, и я просто поддержал его. Просто для полноты позвольте мне бросить в другую:
R> q("no")
за которым следует
M-x R
чтобы создать новый сеанс, который перечитывает .Rprofile
. Легко, быстро и дешево.
Кроме того, в моей книге есть частные пакеты.
Ответ 4
Другая альтернатива: сохранить функции в отдельном файле, который получен в .RProfile
. Вы можете повторно загрузить содержимое непосредственно из R в свободное время.
Ответ 5
Я нахожу, что часто моя среда R забивается различными объектами, когда я создаю или отлаживаю функцию. Я хотел, чтобы обеспечить эффективную защиту окружающей среды от этих объектов, сохраняя при этом личные функции.
Простая функция ниже была моим решением. Он делает 2 вещи:
1) удаляет все нефункциональные объекты, которые не начинаются с заглавной буквы, а затем
2) сохраняет среду как файл RDatap >
(требуется пакет 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. Но у него есть множество преимуществ: а) страх перед тем, что мои данные очищаются от очистки(), меня дисциплинирует использование R исключительно в качестве процессора, а не базы данных; b) моя основная среда R настолько мала, что я могу сделать резервную копию как приложение электронной почты, c) новые функции автоматически сохраняются (мне не нужно вручную управлять списком личных функций), и d) сохраняются все изменения существующих функций. Конечно, лучшее преимущество - наиболее очевидное... Мне не нужно тратить время на выполнение ls() и проверку объектов, чтобы решить, должны ли они быть rm'd.
Даже если вы не заботитесь о специфике моей системы, функция "ll" в R.oo очень полезна для такого рода вещей. Он может использоваться для реализации практически любого набора правил очистки, которые соответствуют вашему личному стилю программирования.
Патрик Мохр
Ответ 6
n-й, быстрый и грязный вариант, будет использовать lsf.str()
при использовании rm()
, чтобы получить все функции в текущем рабочем пространстве.... и позвольте вам назвать функции по своему усмотрению.
pattern <- paste0('*',lsf.str(), '$', collapse = "|")
rm(list = ls()[-grep(pattern, ls())])
Я согласен, это может быть не лучшая практика, но она выполняет свою работу! (и я должен выборочно чистить после себя в любом случае...)
Ответ 7
Как и в случае с ответом Gavin, следующий загружает файл функций, но не оставляет лишний объект окружения:
if('my_namespace' %in% search()) detach('my_namespace'); source('my_functions.R', attach(NULL, name='my_namespace'))
Это удаляет старую версию пространства имен, если она была присоединена (полезна для разработки), затем присоединяет к ней пустую новую среду с именем my_namespace
и sources my_functions.R
. Если вы не удалите старую версию, вы создадите несколько подключенных сред с тем же именем.
Если вы хотите увидеть, какие функции были загружены, посмотрите на вывод для
ls('my_namespace')
Чтобы разгрузить, используйте
detach('my_namespace')
Эти прикрепленные функции, такие как пакет, не будут удалены с помощью rm(list=ls())
.