2011-01-28 2 views
31

У меня есть несколько удобных функций в моем .Rprofile, например, handy function for returning the size of objects in memory. Иногда мне нравится очищать рабочее пространство без перезагрузки, и я делаю это с помощью rm(list=ls()), который удаляет все мои созданные пользователем объекты и мои пользовательские функции. Я бы очень хотел не взорвать свои пользовательские функции.скрывает личные функции в R

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

ответ

34

Объединить 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" 
+3

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

+2

Возможно, потому, что мы не хотим иметь недокументированные пакеты на CRAN, и если R Core должен был пропустить некоторые проверки, им пришлось бы написать целую кучу кода, чтобы можно было установить и загрузить недостающий пакет. Существуют инструментальные средства, предоставляемые для написания неофициальных пакетов - например, roxygen - поэтому вы поддерживаете исходный файл (без Rd-файлов) и генерируете файлы пакетов из них. –

+2

И вам не нужно документировать каждую функцию. Просто вставьте \ alias {} для каждой функции в один файл справки, и этого должно быть достаточно, чтобы победить проверку. Вам не нужны секции \ usage {} и т. Д., Поэтому не предоставляйте их. Этот трюк используется довольно часто для внутренних функций пакета до того, как NAMESPACES были широко использованы. –

20

Вот два способа:

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").

10

Ответ Гэвина замечательный, и я просто поддержал его. Просто для полноты, позвольте мне бросить в другом:

R> q("no") 

следует

M-x R 

создать новую сессию --- который перечитывает .Rprofile. Легко, быстро и дешево.

Помимо этого, в моей книге есть частные пакеты.

+3

Предполагая, что один находится в ESS. Который я есть. За исключением случаев, когда я этого не делаю. –

+1

Но тогда это приглашение оболочки, и мы перезапускаем littler. Даже быстрее :) –

3

Другая альтернатива: сохранить функции в отдельном файле, который получен в пределах .RProfile. Вы можете повторно загрузить содержимое прямо из R в свободное время.

2

Я нахожу, что часто, когда я создаю или отлаживаю функцию, моя среда R забивается различными объектами. Мне нужен был способ эффективно защитить окружающую среду от этих объектов, сохраняя при этом личные функции.

Простая функция ниже была моим решением. Это делает 2 вещи: 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. Но у него есть множество преимуществ: а) страх перед тем, что мои данные очищаются от очистки(), меня дисциплинирует использование R исключительно в качестве процессора, а не базы данных; b) моя основная среда R настолько мала, что я могу сделать резервную копию как приложение электронной почты , c) новые функции автоматически сохраняются (мне не нужно вручную управлять списком личных функций), и d) сохраняются все изменения существующих функций. Конечно, лучшее преимущество - самое очевидное ... Мне не нужно тратить время на выполнение ls() и рассмотрение объектов, чтобы решить, должны ли они быть rm'd.

Даже если вы не заботитесь о специфике моей системы, функция «ll» в R.oo очень полезна для такого рода вещей. Его можно использовать для реализации практически любого набора правил очистки, которые соответствуют вашему личному стилю программирования.

Patrick Mohr

0

энный, быстрый и грязный вариант, будет использовать lsf.str() при использовании rm(), чтобы получить все функции в текущем рабочем пространстве. ... и позвольте вам назвать функции по вашему желанию.

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

Согласен, это может быть не лучшая практика, но она выполняет свою работу! (и я должен выборочно чистить после себя в любом случае ...)

0

Подобный ответ Гэвина, следующий загружает файл функций, но не выходя дополнительный объект среды вокруг:

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()).

Смежные вопросы