Cuando emprendo 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 sea un placer trabajar con mi código? Estoy pensando en cosas como
- Colocación de funciones en archivos fuente
- Cuándo dividir algo en otro archivo fuente
- Lo que 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.
- Tratar (como {?
- Poner cosas como)} en 1 o 2 líneas?
Básicamente, ¿cuáles son sus reglas generales para organizar grandes scripts R?
r
package
conventions
code-organization
project-organization
Dan Goldstein
fuente
fuente
ProjectTemplate
paquete.Respuestas:
La respuesta estándar es usar paquetes: consulte el manual de Extensiones de Writing R , así como diferentes tutoriales en la web.
Te lo dá
R CMD check
Solo corriendo
source()
el código funciona para fragmentos realmente 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 'cómo editar', el manual R Internals tiene excelentes estándares de codificación R en la Sección 6. De lo contrario, tiendo a usar valores predeterminados en el modo ESS de Emacs .
Actualización 2008-Ago-13: David Smith acaba de blogs sobre la Guía de estilo de Google R .
fuente
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, para colocar las funciones de un archivo dentro de un entorno (lo que cualquier otro idioma llama un "espacio de nombres") y adjuntarlo. Por ejemplo, hice un grupo de 'util' de funciones así:
Todo esto está en un archivo util.R . Cuando lo obtiene, obtiene el entorno 'util' para que pueda llamar
util$bgrep()
y tal; pero, además, laattach()
llamada lo hace tan justobgrep()
y funciona directamente. Si no pusiera todas esas funciones en su propio entorno, contaminarían el espacio de nombres de nivel superior del intérprete (el que sels()
muestra).Estaba tratando de simular el sistema de Python, donde cada archivo es un módulo. Sería mejor tenerlo, pero parece estar bien.
fuente
sys.source
:MyEnv <- attach(NULL, name=s_env); sys.source(file, MyEnv)
. Incluso declaro (en su propio entorno) al inicio una funciónsys.source2
que buscará si ya existe un entorno con el mismo nombre y alimenta este en lugar de crear uno nuevo. Hace que agregar funciones personales sea rápido, fácil y un poco organizado :-)Esto puede sonar un poco obvio, especialmente si eres un programador, pero así es como pienso en las unidades lógicas y físicas de código.
No sé si este es su caso, pero cuando estoy trabajando en R, rara vez comienzo con un gran programa complejo en mente. Normalmente comienzo en un script y separo el código en unidades lógicamente separables, a menudo usando funciones. La manipulación de datos y el código de visualización se colocan en sus propias funciones, etc. Y estas funciones se agrupan en una sección del archivo (manipulación de datos en la parte superior, luego visualización, etc.). En última instancia, debe pensar en cómo facilitarle el mantenimiento de su secuencia de comandos y reducir la tasa de defectos.
El grado de precisión de sus funciones variará y existen varias reglas generales: 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 admite llamadas por referencia, por lo general varío para hacer que mis funciones sean demasiado finas cuando se trata de pasar marcos de datos o estructuras similares. Pero esto puede ser una sobrecompensación 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 Primero, si el archivo se hace demasiado grande y desplazarse entre las unidades lógicamente no relacionadas es una molestia. Segundo, si tengo funciones que pueden ser reutilizadas por otros programas. Normalmente empiezo colocando alguna unidad agrupada, digamos funciones de manipulación de datos, en un archivo separado. Entonces puedo obtener este archivo de cualquier otro script.
Si va a implementar sus funciones, debe comenzar a pensar en los paquetes. No despliegue el código R en producción o para su reutilización por otros por varias razones (brevemente: la cultura de la organización prefiere otros idiomas, preocupaciones sobre el rendimiento, GPL, etc.). Además, tiendo a refinar y agregar constantemente a mis colecciones de archivos de origen, y prefiero no tratar con paquetes cuando hago un cambio. Por lo tanto, debe consultar las otras respuestas relacionadas con el paquete, como Dirk, para obtener más detalles sobre este frente.
Finalmente, creo que su pregunta no es necesariamente particular para R. Realmente recomendaría leer Code Complete de Steve McConnell, que contiene mucha sabiduría sobre tales problemas y prácticas de codificación en general.
fuente
Estoy de acuerdo con el consejo de Dirk! En mi humilde opinión, organizar sus programas desde scripts simples hasta paquetes documentados es, para la programación en R, como cambiar de Word a TeX / LaTeX para escribir. Recomiendo echar un vistazo a la muy útil Creación de paquetes R: un tutorial de Friedrich Leisch.
fuente
Mi respuesta concisa:
Creo que R se usa cada vez más en la producción, por lo que la necesidad de código reutilizable es mayor que antes. El intérprete me parece mucho más robusto 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 ahorrar en el esfuerzo de desarrollo. Si el tiempo de ejecución solo fuera el problema, todos estaríamos escribiendo ensamblador.
fuente
He tenido la intención de descubrir cómo escribir paquetes, pero no he invertido el tiempo. Para cada uno de mis miniproyectos, mantengo todas mis funciones de bajo nivel en una carpeta llamada 'funciones /', y las obtengo 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 adjuntar), y lo completarán con las funciones contenidas en los archivos .r en mi directorio 'funciones /' (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 llaman las funciones de alto nivel (invocando las funciones de bajo nivel).
Cuando realiza cambios, siempre puede volver a obtenerlos con las mismas líneas, o usar algo como
para evaluar adiciones / modificaciones en el entorno que creó.
Es un error, lo sé, pero evita tener que ser demasiado formal al respecto (pero si tienes la oportunidad, aliento el sistema de paquetes; con suerte, 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 las sigo libremente pero no uso demasiadas llaves en R):
http://www1.maths.lth.se/help/R/RCC/
Hay otras "convenciones" con respecto al uso de [, drop = FALSE] y <- como lo sugirió el operador de asignación en varias presentaciones (generalmente keynote) en useR! conferencias, pero no creo que ninguna de estas sea estricta (aunque [, drop = FALSE] es útil para programas en los que no está seguro de la entrada que espera).
fuente
Cuenta conmigo como otra persona a favor de los paquetes. Admitiré que soy bastante pobre en escribir páginas de manual y viñetas hasta que tenga que hacerlo (es decir, ser liberado), pero es una forma realmente útil de agrupar la fuente doe. Además, si te tomas en serio el mantenimiento de tu código, los puntos que menciona Dirk entran en juego.
fuente
Yo tambien estoy de acuerdo. Use la función package.skeleton () para comenzar. Incluso si cree que su código puede no volver a ejecutarse nuevamente, puede ayudarlo a motivarlo a crear un código más general que pueda ahorrarle tiempo más adelante.
En cuanto al acceso al entorno global, eso es fácil con el operador << -, aunque no se recomienda.
fuente
Como todavía no he aprendido a escribir paquetes, siempre me he organizado buscando sub scripts. Es similar a las clases de escritura pero no tan complicado. No es programáticamente elegante, pero creo que construyo análisis con el tiempo. Una vez que tengo una gran sección que funciona, a menudo la muevo a un script diferente y la obtengo, ya que usará los objetos del espacio de trabajo. Tal vez necesito importar datos de varias fuentes, ordenarlos todos y encontrar las intersecciones. Podría poner esa sección en un script adicional. Sin embargo, si desea distribuir su "aplicación" para otras personas, o si 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 modificarlo.
fuente
También he estado buscando el santo grial del flujo de trabajo adecuado para armar un proyecto R grande. El año pasado encontré este paquete llamado rsuite y, ciertamente, era lo que estaba buscando. Este paquete R se desarrolló explícitamente para la implementación de proyectos R grandes, pero descubrí que se puede usar para proyectos R más pequeños, medianos y grandes. Daré enlaces a ejemplos del mundo real en un minuto (a continuación), pero primero quiero explicar el nuevo paradigma de construir proyectos de R con
rsuite
.Nota. No soy el creador o desarrollador de
rsuite
.Hemos estado haciendo proyectos mal con RStudio; El objetivo no debe ser la creación de un proyecto o un paquete, sino un alcance mayor. En rsuite crea un superproyecto o proyecto maestro, que contiene los proyectos R estándar y los paquetes R, en todas las combinaciones posibles.
Al tener un superproyecto R, ya no necesita Unix
make
para administrar los niveles inferiores de los proyectos R debajo; usa scripts R en la parte superior. Deja que te enseñe. Cuando crea un proyecto maestro rsuite, obtiene esta estructura de carpetas:La carpeta
R
es donde coloca sus scripts de gestión de proyectos, los que reemplazaránmake
.La carpeta
packages
es la carpeta dondersuite
se encuentran todos los paquetes que componen el superproyecto. También puede copiar y pegar un paquete que no es accesible desde Internet, y rsuite también lo compilará.la carpeta
deployment
es dondersuite
escribirá todos los binarios de paquetes que se indicaron en losDESCRIPTION
archivos de paquetes . Entonces, esto hace que, por sí mismo, proyectes un tiempo accros totalmente reproducible.rsuite
viene con un cliente para todos los sistemas operativos. Los he probado todos. Pero también puede instalarlo como unaddin
RStudio.rsuite
También le permite construir unaconda
instalación aislada en su propia carpetaconda
. Este no es un entorno sino una instalación física de Python derivada de Anaconda en su máquina. Esto funciona junto con los RSystemRequirements
, desde los cuales puede instalar todos los paquetes de Python que desee, desde cualquier canal conda que desee.También puede crear repositorios locales para extraer paquetes R cuando esté desconectado, o si desea construir todo más rápido.
Si lo desea, también puede construir el proyecto R como un archivo zip y compartirlo con sus colegas. Se ejecutará, siempre que sus colegas tengan instalada la misma versión R.
Otra opción es construir un contenedor de todo el proyecto en Ubuntu, Debian o CentOS. Entonces, en lugar de compartir un archivo zip con la compilación de su proyecto, comparte todo el
Docker
contenedor con su proyecto listo para ejecutarse.He estado experimentando mucho con
rsuite
buscando la reproducibilidad total y evito depender de los paquetes que uno instala en el entorno global. Esto es incorrecto porque tan pronto como instala una actualización de paquete, el proyecto, la mayoría de las veces, deja de funcionar, especialmente aquellos paquetes con llamadas muy específicas a una función con ciertos parámetros.Lo primero que comencé a experimentar fue con los
bookdown
libros electrónicos. Nunca he tenido la suerte de tener un libro para sobrevivir a la prueba del tiempo por más de seis meses. Entonces, lo que hice fue convertir el proyecto original de bookdown para seguir elrsuite
marco. Ahora, no tengo que preocuparme por actualizar mi entorno global R, porque el proyecto tiene su propio conjunto de paquetes en eldeployment
carpeta.Lo siguiente que hice fue crear proyectos de aprendizaje automático, pero en el
rsuite
camino. Un proyecto maestro, orquestador en la parte superior, y todos los subproyectos y paquetes que estén bajo el control del maestro. Realmente cambia la forma en que codifica con R, haciéndolo más productivo.Después de eso comencé a trabajar en un nuevo paquete mío llamado
rTorch
. Esto fue posible, en gran parte, debido arsuite
; te permite pensar e ir a lo grande.Sin embargo, un consejo. Aprender
rsuite
no es fácil. Debido a que presenta una nueva forma de crear proyectos R, se siente difícil. No te preocupes por los primeros intentos, continúa subiendo la cuesta hasta que lo hagas. Requiere un conocimiento avanzado de su sistema operativo y de su sistema de archivos.Espero que algún día
RStudio
nos permita generar proyectos de orquestación comorsuite
hace desde el menú. Sería genial.Enlaces:
RSuite GitHUb repo
bookdown de r4ds
Keras y tutorial brillante
moderno-libro-rsuite
interpretable_ml-rsuite
IntroducciónMachineLearningWithR-rsuite
clark-intro_ml-rsuite
hyndman-bookdown-rsuite
statistic_rethinking-rsuite
fread-benchmarks-rsuite
dataviz-rsuite
retail-segmentation-h2o-tutorial
telco-customer-churn-tutorial
sclerotinia_rsuite
fuente
R está bien para uso interactivo y pequeños scripts, pero no lo usaría para un programa grande. Usaría un lenguaje convencional para la mayoría de la programación y lo envolvería en una interfaz R.
fuente
Rcpp
paquete, incluido el código C ++ en los programas R, se vuelve bastante sencillo. Por lo tanto, reescribir ciertas partes del código R puede integrarse en R con bastante facilidad. Además, la llegada de RStudio ha introducido un IDE para R, aunque quizás aún no sea tan poderoso como Visual Studio.