2011-01-28 14 views
31

Tengo algunas funciones de conveniencia en mi .Rprofile, como este handy function for returning the size of objects in memory. A veces me gusta limpiar mi área de trabajo sin reiniciar y hago esto con rm(list=ls()) que borra todos mis objetos creados por el usuario Y mis funciones personalizadas. Realmente me gustaría no explotar mis funciones personalizadas.ocultando funciones personales en R

Una forma de evitar esto parece ser la creación de un paquete con mis funciones personalizadas para que mis funciones terminen en su propio espacio de nombres. Eso no es particularmente difícil, pero ¿hay alguna manera más fácil de garantizar que las funciones personalizadas no sean eliminadas por rm()?

Respuesta

34

Combina attach y sys.source para crear un entorno y anexar ese entorno. Aquí tengo dos funciones en el archivo my_fun.R:

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

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

Antes de cargar estas funciones, que son obviamente no encontrado:

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

Crear un entorno y la fuente el archivo en él:

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

Todavía no es visible ya que no hemos adjuntado nada

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

y cuando lo hacemos, que son visibles, y porque hemos adjuntado una copia del medio ambiente a la ruta de búsqueda de las funciones sobreviven siendo 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 

aún así creo que sería mejor con su propio paquete personal, pero lo anterior podría ser suficiente mientras tanto. Solo recuerde que la copia en la ruta de búsqueda es solo eso, una copia . Si las funciones son bastante estables y no las está editando, lo anterior puede ser útil, pero probablemente sea más complicado de lo que vale si está desarrollando las funciones y modificándolas.

Una segunda opción es sólo les nombrar a todos .foo en lugar de foo como ls() no volverá objetos nombrados como que a menos que el argumento all = TRUE se establece:

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

Los paquetes personales están bien para esto, aunque todavía me molesta que tenga que pasar por tantos aros para crear un paquete. ¿Por qué tengo que proporcionar documentación para cada función en un paquete personal? –

+2

Probablemente porque no queremos paquetes no documentados en CRAN, y si R Core permitiera eludir algunas comprobaciones, tendrían que escribir un montón de código para permitir que uno instale y cargue un paquete deficiente. Hay herramientas de usuario proporcionadas para ayudar a escribir paquetes informales, como roxygen, para que pueda mantener un archivo fuente (sin archivos Rd) y generar los archivos del paquete a partir de ellos. –

+2

Y no tiene que documentar cada función. Simplemente inserte un \ alias {} para cada función en un solo archivo de ayuda y eso debería ser suficiente para evitar la comprobación. No necesita \ use {} secciones, etc., así que no las proporcione. Este truco se usa con bastante frecuencia para las funciones internas del paquete antes de que se utilizaran NAMESPACES. –

20

Aquí hay dos maneras:

1) Haga que cada nombre de su función comience con un punto, por ejemplo .f en lugar de f. ls no mostrará estas funciones a menos que use ls(all.names = TRUE), por lo tanto, no se pasarán a su comando rm.

o,

2) ponga esto en su .Rprofile

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

Las funciones aparecerán como un componente llamado "MyFunctions" en su lista de búsqueda en lugar de en su espacio de trabajo y serán accesibles casi lo mismo que si estuvieran en su área de trabajo. search() mostrará su lista de búsqueda y ls("MyFunctions") listará los nombres de las funciones que adjuntó.Como no están en su área de trabajo, el comando rm que usa normalmente no los eliminará. Si desea eliminarlos, utilice detach("MyFunctions").

10

La respuesta de Gavin es maravillosa, y acabo de subirla. Simplemente por la totalidad, déjame echar en otro:

R> q("no") 

seguido por

M-x R 

para crear una nueva sesión --- que re-lee el .Rprofile. Fácil, rápido y barato.

Aparte de eso, los paquetes privados son el camino en mi libro.

+3

Presumiendo que uno está en ESS. Cuál soy yo Excepto cuando no soy. –

+1

Pero luego es un mensaje de shell y reiniciamos littler. Aun más rápido :) –

3

Otra alternativa: mantener las funciones en un archivo separado que se origina en .RProfile. Puede volver a obtener los contenidos directamente desde dentro de R en su tiempo libre.

2

Me parece que a menudo mi entorno R se llena de varios objetos cuando estoy creando o depurando una función. Quería una forma de mantener eficientemente el medio ambiente libre de estos objetos mientras conservaba las funciones personales.

La función simple a continuación fue mi solución. Lo hace 2 cosas: 1), borra los objetos que no son de función que no comienzan con una letra mayúscula y luego 2) protege el medio ambiente como un archivo rdata

(requiere el paquete 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)) 
} 

para utilizar esta función 3 reglas deben mantenerse siempre:
1) mantener todos los datos externa a R.
2) utilizar nombres que comienzan con una letra mayúscula para objetos no funcionales que quiero mantener de forma permanente disponible.
3) Las funciones obsoletas se deben eliminar manualmente con rm.

Obviamente, esta no es una solución general para todos ... y potencialmente desastrosa si no se cumplen las reglas n. ° 1 y n. ° 2. Pero tiene numerosas ventajas: a) el miedo a que mis datos se nublen con la limpieza() me mantiene disciplinado sobre el uso de R exclusivamente como procesador y no como base de datos, b) mi entorno R principal es tan pequeño que puedo hacer copias de seguridad como un archivo adjunto de correo electrónico , c) las nuevas funciones se guardan automáticamente (no es necesario que administre manualmente una lista de funciones personales) yd) se conservan todas las modificaciones de funciones preexistentes. Por supuesto, la mejor ventaja es la más obvia ... No tengo que perder tiempo haciendo ls() y revisando los objetos para decidir si deben ser corregidos.

Incluso si no te importan los detalles de mi sistema, la función "ll" en R.oo es muy útil para este tipo de cosas. Se puede usar para implementar casi cualquier conjunto de reglas de limpieza que se ajusten a su estilo de programación personal.

Patrick Mohr

0

Un enésimo, opción rápida y sucia, sería utilizar lsf.str() cuando se utiliza rm(), para obtener todas las funciones en el área de trabajo actual. ... y deja que nombre las funciones como desee.

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

Estoy de acuerdo, puede que no sea la mejor práctica, ¡pero hace el trabajo! (Y tengo que limpiar selectivamente después de mí de todos modos ...)

0

Similar a la respuesta de Gavin, el siguiente carga un archivo de funciones, pero sin dejar un objeto entorno extra alrededor:

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

Esto elimina la versión antigua del espacio de nombres si se adjunta (útil para el desarrollo) , luego agrega un nuevo entorno vacío llamado my_namespace y fuentes my_functions.R en él. Si no elimina la versión anterior, creará varios entornos adjuntos del mismo nombre.

En caso de que deseen ver qué funciones se han cargado, mira a la salida para

ls('my_namespace') 

para descargar, usar

detach('my_namespace') 

Estas funciones agregadas, como un paquete, no se eliminarán por rm(list=ls()).