¿Cómo se puede generar el archivo R Markdown como `source (‘myfile.r’)`?

A menudo tengo un archivo R Markdown principal o un archivo Knitr LaTeX en el que obtengo otro archivo R (por ejemplo, para el procesamiento de datos). Sin embargo, estaba pensando que en algunos casos sería beneficioso que estos archivos de origen sean sus propios documentos reproducibles (por ejemplo, un archivo R Markdown que no solo incluye comandos para el procesamiento de datos, sino que también produce un documento reproducible que explica el procesamiento de datos). decisiones).

Por lo tanto, me gustaría tener un comando como source('myfile.rmd') en mi archivo principal de R Markdown. que extraería y fuente de todo el código R dentro de los fragmentos de código R de myfile.rmd . Por supuesto, esto da lugar a un error.

El siguiente comando funciona:

 ```{r message=FALSE, results='hide'} knit('myfile.rmd', tangle=TRUE) source('myfile.R') ``` 

donde results='hide' podría omitirse si se deseaba obtener resultados. Es decir, knitr genera el código R de myfile.rmd en myfile.R .

Sin embargo, no parece perfecto:

  • resulta en la creación de un archivo adicional
  • debe aparecer en su propio fragmento de código si se requiere controlar la visualización.
  • No es tan elegante como una source(...) simple source(...) .

Por lo tanto, mi pregunta es : ¿hay una manera más elegante de obtener el código R de un archivo R Markdown?

Parece que estás buscando un trazador de líneas. ¿Qué hay de poner esto en su .Rprofile ?

 ksource <- function(x, ...) { library(knitr) source(purl(x, output = tempfile()), ...) } 

Sin embargo, no entiendo por qué desea generar source() el código en el archivo Rmd. Me refiero a que knit() ejecutará todo el código en este documento, y si extraes el código y lo ejecutas en un fragmento, todo el código se ejecutará dos veces cuando knit() este documento (te ejecutas dentro de ti). Las dos tareas deben estar separadas.

Si realmente desea ejecutar todo el código, RStudio lo ha simplificado bastante: Ctrl + Shift + R Básicamente llama a purl() y source() detrás de la escena.

Factorice el código común en un archivo R separado, y luego procese ese archivo R en cada archivo Rmd que desee.

así que, por ejemplo, digamos que tengo dos informes que tengo que hacer, Flu Outbreaks and Guns vs Butter Analysis. Naturalmente, crearía dos documentos Rmd y terminaría con eso.

Ahora supongamos que viene el jefe y quiere ver las variaciones de los brotes de gripe frente a los precios de la mantequilla (controlando la munición de 9 mm).

  • Copiar y pegar el código para analizar los informes en el nuevo informe es una mala idea para la reutilización del código, etc.
  • Quiero que se vea bien.

Mi solución fue factorizar el proyecto en estos archivos:

  • Flu.Rmd
    • flu_data_import.R
  • Guns_N_Butter.Rmd
    • guns_data_import.R
    • butter_data_import.R

dentro de cada archivo Rmd tendría algo como:

 ```{r include=FALSE} source('flu_data_import.R') ``` 

El problema aquí es que perdemos reproducibilidad. Mi solución a eso es crear un documento secundario común para incluir en cada archivo Rmd. Entonces, al final de cada archivo Rmd que creo, agrego esto:

 ```{r autodoc, child='autodoc.Rmd', eval=TRUE} ``` 

Y, por supuesto, autodoc.Rmd:

 Source Data & Code ---------------------------- 
```{r sourcedata, echo=FALSE, results='asis', warnings=FALSE} if(!exists(autodoc.skip.df)) { autodoc.skip.df <- list() } #Generate the following table: for (i in ls(.GlobalEnv)) { if(!i %in% autodoc.skip.df) { itm <- tryCatch(get(i), error=function(e) NA ) if(typeof(itm)=="list") { if(is.data.frame(itm)) { cat(sprintf("### %s\n", i)) print(xtable(itm), type="html", include.rownames=FALSE, html.table.attributes=sprintf("class='exportable' id='%s'", i)) } } } } ``` ### Source Code ```{r allsource, echo=FALSE, results='asis', warning=FALSE, cache=FALSE} fns <- unique(c(compact(llply(.data=llply(.data=ls(all.names=TRUE), .fun=function(x) {a<-get(x); c(normalizePath(getSrcDirectory(a)),getSrcFilename(a))}), .fun=function(x) { if(length(x)>0) { x } } )), llply(names(sourced), function(x) c(normalizePath(dirname(x)), basename(x))))) for (itm in fns) { cat(sprintf("#### %s\n", itm[2])) cat("\n```{r eval=FALSE}\n") cat(paste(tryCatch(readLines(file.path(itm[1], itm[2])), error=function(e) sprintf("Could not read source file named %s", file.path(itm[1], itm[2]))), sep="\n", collapse="\n")) cat("\n```\n") } ```

NB, esto está diseñado para el flujo de trabajo Rmd -> html. Esto será un desastre si vas con latex o cualquier otra cosa. Este documento Rmd busca en el entorno global todos los archivos fuente () e incluye su fuente al final de su documento. Incluye jquery ui, tablesorter y configura el documento para usar un estilo de acordeón para mostrar / ocultar los archivos de origen. Es un trabajo en progreso, pero puede adaptarlo a sus propios usos.

No es de una sola línea, lo sé. Espero que al menos te dé algunas ideas 🙂

Si estás justo detrás del código, creo que algo en este sentido debería funcionar:

  1. Lea el archivo markdown / R con readLines
  2. Usa grep para encontrar los fragmentos del código, buscando líneas que comiencen con <<< por ejemplo
  3. Tome el subconjunto del objeto que contiene las líneas originales para obtener solo el código
  4. Vuelca esto a un archivo temporal usando writeLines
  5. Fuente este archivo en su sesión R

Envolver esto en una función debería darle lo que necesita.

Probablemente uno debería comenzar a pensar diferente. Mi problema es el siguiente: escribe cada código que normalmente tendrías en un fragmento .Rmd en un archivo .R. Y para el documento Rmd que usas para tejer, es decir, un html, solo te queda

 ```{R Chunkname, Chunkoptions} source(file.R) ``` 

De esta forma, probablemente creará un grupo de archivos .R y perderá la ventaja de procesar todo el código “fragmento tras fragmento” usando ctrl + alt + n (o + c, pero normalmente esto no funciona). Pero, leí el libro sobre investigación reproducible del Sr. Gandrud y me di cuenta de que definitivamente usa los archivos knitr y .Rmd únicamente para crear archivos html. El análisis principal en sí es un archivo .R. Creo que los documentos .Rmd crecen demasiado rápido si comienzas a hacer todo tu análisis dentro.

El siguiente truco funcionó bien para mí:

 library(readr) library(stringr) source_rmd <- function(file_path) { stopifnot(is.character(file_path) && length(file_path) == 1) .tmpfile <- tempfile(fileext = ".R") .con <- file(.tmpfile) on.exit(close(.con)) full_rmd <- read_file(file_path) codes <- str_match_all(string = full_rmd, pattern = "```(?s)\\{r[^{}]*\\}\\s*\\n(.*?)```") stopifnot(length(codes) == 1 && ncol(codes[[1]]) == 2) codes <- paste(codes[[1]][, 2], collapse = "\n") writeLines(codes, .con) flush(.con) cat(sprintf("R code extracted to tempfile: %s\nSourcing tempfile...", .tmpfile)) source(.tmpfile) } 

Recomiendo mantener el código principal de análisis y cálculo en el archivo .R e importar los fragmentos según sea necesario en el archivo .Rmd. He explicado el proceso aquí .