Подтвердить что ты не робот

Скрытие личных функций в R

У меня есть несколько удобных функций в моем .Rprofile, таком как удобная функция для возврата размера объектов в память. Иногда мне нравится очищать рабочее пространство без перезагрузки, и я делаю это с помощью rm(list=ls()), который удаляет все мои созданные пользователем объекты и мои пользовательские функции. Я бы очень хотел не взорвать свои пользовательские функции.

Похоже, что это создает пакет с моими пользовательскими функциями, чтобы мои функции попадали в собственное пространство имен. Это не особенно сложно, но есть ли более простой способ гарантировать, что пользовательские функции не будут убиты rm()?

4b9b3361

Ответ 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) сохраняет среду как файл RData​​p >

(требуется пакет 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()).