r

Estrategias para repetir gran parte del análisis.



(7)

Me encuentro en la posición de haber completado una gran parte del análisis y ahora necesito repetir el análisis con suposiciones de entrada ligeramente diferentes.

El análisis, en este caso, involucra análisis de conglomerados, graficando varios gráficos y exportando ID de conglomerados y otras variables de interés. El punto clave es que es un análisis extenso, y debe repetirse y compararse solo dos veces.

Yo considere:

  • Creando una función. Esto no es ideal, porque luego tengo que modificar mi código para saber si estoy evaluando en la función o en los entornos principales. Este esfuerzo adicional parece excesivo, hace que sea más difícil de depurar y puede introducir efectos secundarios.
  • Envolverlo en un bucle for. Nuevamente, no es ideal, porque entonces tengo que crear variables de indexación, que también pueden introducir efectos secundarios.
  • Creando un código de preámbulo, envolviendo el análisis en un archivo separado y source . Esto funciona, pero parece muy feo y subóptimo.

El objetivo del análisis es terminar con un conjunto de objetos (en una lista, o en archivos de salida separados) que puedo analizar más en busca de diferencias.

¿Cuál es una buena estrategia para tratar este tipo de problema?


Es demasiado tarde para usted aquí, pero uso Sweave mucho, y lo más probable es que haya usado un archivo de Sweave desde el principio (por ejemplo, si sé que el producto final debe ser algún tipo de informe).

Para repetir partes del análisis por segunda y tercera vez, hay dos opciones:

  • si los resultados son más bien "independientes" (es decir, deberían producir 3 informes, la comparación significa que los informes se inspeccionan uno al lado del otro), y la entrada modificada se presenta en forma de nuevos archivos de datos, que van a su propio directorio junto con una copia de el archivo Sweave, y creo informes separados (similar a la fuente, pero se siente más natural para Sweave que para la fuente simple).

  • si prefiero hacer exactamente lo mismo una o dos veces dentro de un archivo de Sweave, consideraría reutilizar fragmentos de código. Esto es similar al feo for-loop.

    La razón es que, por supuesto, los resultados están juntos para la comparación, que sería la última parte del informe.

  • Si está claro desde el principio que habrá algunos conjuntos de parámetros y una comparación, escribo el código de manera que tan pronto como esté bien con cada parte del análisis, se envuelva en una función (es decir, estoy escribiendo la función en la ventana del editor, pero evalúe las líneas directamente en el área de trabajo mientras escribe la función).

Dado que estás en la situación descrita, estoy de acuerdo con Nick: nada está mal con la source y todo lo demás significa mucho más esfuerzo ahora que ya lo tienes como script.


Hacer que el código sea reutilizable toma tiempo, esfuerzo y contiene algunos desafíos adicionales, como usted mismo lo menciona.

La pregunta sobre si invertir es probablemente el problema clave en informática (si no en muchos otros campos): ¿escribo un script para cambiar el nombre de 50 archivos de una manera similar, o continúo y les cambio el nombre manualmente?

La respuesta, creo, es altamente personal e incluso entonces, diferente caso por caso. Si es fácil con la programación, tal vez prefiera optar por la ruta de reutilización, ya que el esfuerzo para usted será relativamente bajo (e incluso entonces, a los programadores normalmente les gusta aprender nuevos trucos, por lo que es una motivación oculta, a menudo contraproducente).

Dicho esto, en su caso particular: me quedaría con la opción de aprovisionamiento: dado que planea reutilizar el código solo 2 veces más, probablemente se desperdicie un mayor esfuerzo (indica que el análisis es bastante extenso). ¿Y si no es una solución elegante? Nadie te verá hacerlo, y todos estarán contentos con los rápidos resultados.

Si resulta en un año o más que la reutilización es más alta de lo esperado, aún puede invertir. Y para ese momento, también tendrá (al menos) tres casos para los cuales puede comparar los resultados de la versión reescrita y funky reutilizable de su código con sus resultados actuales.

Si / cuando sé por adelantado que voy a reutilizar el código, trato de tenerlo en cuenta mientras lo desarrollo. De cualquier manera, casi nunca escribo código que no esté en una función (bueno, salvo las dos líneas para SO y otros análisis listos para usar): encuentro que esto hace que sea más fácil para mí estructurar mis pensamientos.


Me gusta trabajar con la combinación de un pequeño script de shell, un programa de recorte de PDF y Sweave en esos casos. Eso le devuelve buenos informes y lo alienta a buscar. Normalmente, trabajo con varios archivos, casi como crear un paquete (al menos creo que se siente así :). Tengo un archivo separado para el malabarismo de datos y archivos separados para diferentes tipos de análisis, como descripttiveStats.R, regressions.R por ejemplo.

por cierto aquí está mi pequeño script de shell,

#!/bin/sh R CMD Sweave docSweave.Rnw for file in `ls pdfs`; do pdfcrop pdfs/"$file" pdfs/"$file" done pdflatex docSweave.tex open docSweave.pdf

El archivo Sweave generalmente genera los archivos R mencionados anteriormente cuando es necesario. No estoy seguro de si eso es lo que está buscando, pero esa es mi estrategia hasta ahora. Al menos creo que crear informes transparentes y reproducibles es lo que ayuda a seguir al menos una estrategia.



Si es posible, configure parámetros que difieran entre conjuntos / ejecuciones / experimentos en un archivo de parámetros externo. Luego, puede obtener el código, llamar a una función, incluso utilizar un paquete, pero las operaciones están determinadas por un pequeño conjunto de parámetros definidos externamente.

Por ejemplo, JSON funciona muy bien para esto y los paquetes RJSONIO y rjson permiten cargar el archivo en una lista. Supongamos que lo carga en una lista llamada parametersNN.json. Un ejemplo es el siguiente:

{ "Version": "20110701a", "Initialization": { "indices": [1,2,3,4,5,6,7,8,9,10], "step_size": 0.05 }, "Stopping": { "tolerance": 0.01, "iterations": 100 } }

Guárdelo como "parameters01.json" y cárguelo como:

library(RJSONIO) Params <- fromJSON("parameters.json")

y tu estas fuera y corriendo (NB: Me gusta usar la versión única #s dentro de mis archivos de parámetros, solo para poder identificar el conjunto más adelante, si estoy viendo la lista de "parámetros" dentro de la R.) Simplemente llame a su script y señale los parámetros archivo, por ejemplo:

Rscript --vanilla MyScript.R parameters01.json

luego, dentro del programa, identifique el archivo de parámetros de la función commandArgs() .

Más adelante, puede dividir el código en funciones y paquetes, pero esta es probablemente la forma más fácil de hacer que un script de vainilla se pueda generalizar a corto plazo, y es una buena práctica a largo plazo, ya que el código debe separarse de la especificación de Ejecutar / conjunto de datos / parámetros dependientes del experimento.

Edición: para ser más precisos, incluso especificaría directorios o archivos de entrada y salida (o denominación de patrones / prefijos) en el JSON. Esto deja muy claro cómo un conjunto de parámetros condujo a un conjunto de salida en particular. Todo lo que está en medio es solo un código que se ejecuta con una parametrización dada, pero el código realmente no debería cambiar mucho, ¿verdad?

Actualización: Tres meses, y muchos miles de ejecuciones, más sabia que mi respuesta anterior, diría que el almacenamiento externo de parámetros en JSON es útil para 1-1000 ejecuciones diferentes. Cuando los parámetros o las configuraciones se multiplican por miles, es mejor cambiar a una base de datos para la administración de la configuración. Cada configuración puede originarse en un JSON (o XML), pero ser capaz de lidiar con diferentes diseños de parámetros requiere una solución a mayor escala, para la cual una base de datos como SQLite (a través de RSQLite ) es una solución fina.

Me doy cuenta de que esta respuesta es una exageración para la pregunta original: cómo repetir el trabajo solo un par de veces, con algunos cambios de parámetros, pero al escalar cientos o miles de cambios de parámetros en la investigación en curso, se necesitan herramientas más amplias. :)


Tiendo a poner esos resultados en una lista global. Yo uso Common Lisp pero luego R no es tan diferente.


Tu tercera opción no es tan mala. Hago esto en muchos casos. Puede construir un poco más de estructura al colocar los resultados de su código de pre-amplio en entornos y adjuntar el que desea usar para un análisis más detallado. Un ejemplo:

setup1 <- local({ x <- rnorm(50, mean=2.0) y <- rnorm(50, mean=1.0) environment() # ... }) setup2 <- local({ x <- rnorm(50, mean=1.8) y <- rnorm(50, mean=1.5) environment() # ... })

attach(setup1) y ejecutar / fuente su código de análisis

plot(x, y) t.test(x, y, paired = T, var.equal = T) ...

Cuando haya terminado, detach(setup1) y adjunte el segundo.

Ahora, al menos puedes cambiar fácilmente entre configuraciones. Me ayudó un par de veces.