poligono para pairs ordenar librerias grafico graficas graficar grafica ejemplos cuadricula barras r package conventions code-organization project-organization

para - ¿Cómo organizar grandes programas R?



poligono en r (10)

¡Estoy de acuerdo con el consejo de Dirk! En mi humilde opinión, organizar sus programas desde simples scripts hasta paquetes documentados es, para la Programación en R, como cambiar de Word a TeX / LaTeX para escribir. Recomiendo echar un vistazo a los muy útiles Creating R Packages: A Tutorial de Friedrich Leisch.

Cuando realizo un proyecto R de cualquier complejidad, mis guiones rápidamente se vuelven largos y confusos.

¿Cuáles son algunas prácticas que puedo adoptar para que mi código siempre sea un placer trabajar con él? Estoy pensando en cosas como

  • Colocación de funciones en archivos fuente
  • Cuándo dividir algo en otro archivo fuente
  • Qué debería estar en el archivo maestro
  • Usar funciones como unidades organizativas (si esto vale la pena dado que R dificulta el acceso al estado global)
  • Prácticas de sangría / salto de línea.
    • Treat (like {?
    • Pon cosas como)} en 1 o 2 líneas

Básicamente, ¿cuáles son sus reglas básicas para organizar grandes scripts R?


Al no haber aprendido a escribir paquetes todavía, siempre los he organizado al buscar scripts secundarios. Es similar a las clases de escritura, pero no tan complicado. No es programáticamente elegante, pero creo que acumulo análisis a lo largo del tiempo. Una vez que tengo una gran sección que funciona, a menudo la muevo a un script diferente y solo la fuente, ya que usará los objetos del espacio de trabajo. Tal vez deba importar datos de varias fuentes, clasificarlos a todos y encontrar las intersecciones. Podría poner esa sección en un guión adicional. Sin embargo, si desea distribuir su "aplicación" para otras personas, o utiliza alguna entrada interactiva, un paquete es probablemente una buena ruta. Como investigador, rara vez necesito distribuir mi código de análisis, pero A MENUDO necesito aumentarlo o ajustarlo.


Cuentame como otra persona a favor de los paquetes. Debo admitir que soy bastante pobre al escribir páginas de manual y viñetas hasta cuando y cuando sea necesario (es decir, que me liberen), pero es una forma muy útil de agrupar fuentes. Además, si te tomas en serio el mantenimiento de tu código, todos los puntos que Dirk menciona entran en plya.


Esto puede parecer un poco obvio, especialmente si usted es un programador, pero así es como pienso sobre las unidades de código lógico y físico.

No sé si este es tu caso, pero cuando trabajo en R, rara vez comienzo con un gran programa complejo en mente. Normalmente comienzo en una secuencia de comandos y código separado en unidades lógicamente separables, a menudo con funciones. El código de manipulación y visualización de datos se coloca en sus propias funciones, etc. Y tales funciones se agrupan en una sección del archivo (manipulación de datos en la parte superior, luego visualización, etc.). En última instancia, desea pensar en cómo facilitarle el mantenimiento de su secuencia de comandos y disminuir la tasa de defectos.

El grado de precisión / grosor de sus funciones variará y existen varias reglas prácticas: por ejemplo, 15 líneas de código, o "una función debe ser responsable de realizar una tarea que se identifica por su nombre", etc. Su kilometraje variará. . Dado que R no es compatible con la función de referencia por llamada, por lo general hago que mis funciones sean demasiado finas cuando se trata de pasar marcos de datos o estructuras similares. Pero esto puede ser una compensación excesiva por algunos errores tontos de rendimiento cuando comencé con R.

¿Cuándo extraer unidades lógicas en sus propias unidades físicas (como archivos fuente y agrupaciones más grandes como paquetes)? Tengo dos casos En primer lugar, si el archivo es demasiado grande y el desplazamiento entre unidades lógicamente no relacionadas es una molestia. Segundo, si tengo funciones que puedan ser reutilizadas por otros programas. Normalmente empiezo colocando una unidad agrupada, digamos funciones de manipulación de datos, en un archivo separado. Entonces puedo obtener este archivo de cualquier otra secuencia de comandos.

Si va a implementar sus funciones, entonces debe comenzar a pensar en paquetes. No despliego el código R en producción o para su reutilización por otros motivos (brevemente: la cultura orgánica prefiere otros lenguajes, las preocupaciones sobre el rendimiento, la GPL, etc.). Además, tiendo a refinar constantemente y agregar a mis colecciones de archivos de origen, y prefiero no tratar con paquetes cuando realizo un cambio. Por lo tanto, debe consultar las respuestas relacionadas con otros paquetes, como Dirk''s, para obtener más detalles sobre este frente.

Finalmente, creo que su pregunta no es necesariamente específica de R. Realmente recomendaría leer Code Complete de Steve McConnell, que contiene mucha sabiduría acerca de tales cuestiones y las prácticas de codificación en general.


He tenido la intención de descubrir cómo escribir paquetes pero no he invertido el tiempo. Para cada uno de mis mini-proyectos, guardo todas mis funciones de bajo nivel en una carpeta llamada ''functions /'', y las fuentes en un espacio de nombres separado que creo explícitamente.

Las siguientes líneas de código crearán un entorno llamado "myfuncs" en la ruta de búsqueda si aún no existe (usando attach), y lo poblarán con las funciones contenidas en los archivos .r en mi directorio ''functions /'' (usando sys.source). Normalmente pongo estas líneas en la parte superior de mi script principal destinado a la "interfaz de usuario" desde la que se invocan las funciones de alto nivel (que invocan las funciones de bajo nivel).

if( length(grep("^myfuncs$",search()))==0 ) attach("myfuncs",pos=2) for( f in list.files("functions","//.r$",full=TRUE) ) sys.source(f,pos.to.env(grep("^myfuncs$",search())))

Cuando realiza cambios, siempre puede volver a utilizarlos con las mismas líneas, o usar algo como

evalq(f <- function(x) x * 2, pos.to.env(grep("^myfuncs$",search())))

para evaluar adiciones / modificaciones en el entorno que ha creado.

Es sabio, lo sé, pero evito tener que ser demasiado formal al respecto (pero si tienes la oportunidad, aliento el sistema de paquetes, con suerte voy a migrar de esa manera en el futuro).

En cuanto a las convenciones de codificación, esto es lo único que he visto con respecto a la estética (me gustan y sigo sin apretar pero no uso demasiadas llaves en R):

http://www1.maths.lth.se/help/R/RCC/

Existen otras "convenciones" sobre el uso de [, drop = FALSE] y <- como el operador de asignación sugirió en varias presentaciones (por lo general, keynote) en useR! conferencias, pero no creo que ninguna sea estricta (aunque [, drop = FALSE] es útil para programas en los que no está seguro de la información que espera).


La respuesta estándar es usar paquetes: consulte el manual de Writing R Extensions y otros tutoriales en la web.

Te lo dá

  • una forma casi automática de organizar su código por tema
  • lo alienta encarecidamente a que escriba un archivo de ayuda, haciéndole pensar acerca de la interfaz
  • una gran cantidad de controles de cordura a través de R CMD check
  • una oportunidad de agregar pruebas de regresión
  • así como un medio para espacios de nombres.

Simplemente ejecutar source() sobre el código funciona para fragmentos muy cortos. Todo lo demás debe estar en un paquete, incluso si no planea publicarlo, ya que puede escribir paquetes internos para repositorios internos.

En cuanto a la parte de ''cómo editar'', el manual de R Internals tiene excelentes estándares de codificación R en la Sección 6. De lo contrario, tiendo a usar los valores predeterminados en el modo ESS de Emacs .

Actualización 2008-Ago-13: David Smith acaba de publicar un blog sobre la Guía de estilo de Google R.


Me gusta poner diferentes funcionalidades en sus propios archivos.

Pero no me gusta el sistema de paquetes de R. Es bastante difícil de usar.

Prefiero una alternativa ligera, colocar las funciones de un archivo dentro de un entorno (lo que todos los demás idiomas llaman "espacio de nombre") y adjuntarlo. Por ejemplo, hice un grupo de funciones ''util'' de esta manera:

util = new.env() util$bgrep = function [...] util$timeit = function [...] while("util" %in% search()) detach("util") attach(util)

Todo esto en un archivo util.R Cuando lo obtiene, obtiene el entorno ''utilitario'' para que pueda llamar a util$bgrep() y tal; pero además, la llamada attach() hace que sea tan simple bgrep() y tal trabajo directamente. Si no pusiera todas esas funciones en su propio entorno, contaminarían el espacio de nombres de alto nivel del intérprete (el que muestra ls() ).

Estaba intentando simular el sistema de Python, donde cada archivo es un módulo. Eso sería mejor tener, pero parece estar bien.


Mi respuesta concisa:

  1. Escriba sus funciones cuidadosamente, identificando salidas y entradas lo suficientemente generales;
  2. Limite el uso de variables globales;
  3. Use objetos S3 y, cuando corresponda, objetos S4;
  4. Coloque las funciones en paquetes, especialmente cuando sus funciones llamen a C / Fortran.

Creo que R se usa cada vez más en la producción, por lo que la necesidad de un código reutilizable es mayor que antes. El intérprete me parece mucho más sólido que antes. No hay duda de que R es 100-300x más lento que C, pero generalmente el cuello de botella se concentra alrededor de unas pocas líneas de código, que se pueden delegar a C / C ++. Creo que sería un error delegar las fortalezas de R en la manipulación de datos y el análisis estadístico a otro idioma. En estos casos, la penalización de rendimiento es baja, y en cualquier caso vale la pena el ahorro en el esfuerzo de desarrollo. Si el tiempo de ejecución solo fuera el problema, estaríamos todos escribiendo ensamblador.


R está bien para uso interactivo y pequeños guiones, pero no lo usaría para un programa grande. Usaría un lenguaje convencional para la mayoría de la programación y lo incluiría en una interfaz R.


Yo tambien estoy de acuerdo. Use la función package.skeleton () para comenzar. Incluso si cree que su código nunca se ejecutará nuevamente, puede ayudar a motivarlo a crear un código más general que podría ahorrarle tiempo más tarde.

En cuanto al acceso al entorno global, es fácil con el operador << -, aunque no se recomienda.