A menudo tengo un archivo principal R Markdown o un archivo Knitr LaTeX donde tengo source
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 fueran 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 las decisiones de procesamiento de datos ).
Por lo tanto, me gustaría tener un comando como source('myfile.rmd')
en mi archivo principal de R Markdown. que extraería y generaría 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 desea la salida. Es decir, knitr genera el código R de myfile.rmd
en myfile.R
.
Sin embargo, no parece perfecto:
- da como resultado la creación de un archivo adicional
- debe aparecer en su propio fragmento de código si se requiere control sobre la pantalla.
- No es tan elegante como simple
source(...)
.
Por lo tanto, mi pregunta: ¿Existe una forma más elegante de obtener el código R de un archivo R Markdown?
Rmd
archivo. ¿Pero también desea obtener otrosmarkdown
archivos en un archivo que se está tejiendo?include
látex. Si Markdown admite la inclusión de otros documentos de Markdown, debería ser relativamente fácil crear dicha función.Respuestas:
Parece que estás buscando una frase de una sola línea. ¿Qué tal poner esto en tu
.Rprofile
?ksource <- function(x, ...) { library(knitr) source(purl(x, output = tempfile()), ...) }
Sin embargo, no entiendo por qué desea
source()
el código en el archivo Rmd. Quiero decirknit()
, ejecutará todo el código de este documento, y si extrae el código y lo ejecuta en un fragmento, todo el código se ejecutará dos veces cuandoknit()
este documento (se ejecutará usted mismo dentro de sí mismo). Las dos tareas deben estar separadas.Si realmente desea ejecutar todo el código, rstudio ha hecho esta bastante fácil:
Ctrl + Shift + R
. Básicamente llamapurl()
ysource()
detrás de escena.fuente
source()
oknitr::knit()
ejecutar el código. Sé que la gente está menos familiarizada con este último, peropurl()
no es confiable. Has sido advertido: github.com/yihui/knitr/pull/812#issuecomment-53088636caret
requiere un casokernlab
con svm.Factoriza el código común en un archivo R separado y luego genera ese archivo R en cada archivo Rmd en el que quieras.
así que, por ejemplo, digamos que tengo dos informes que necesito hacer, Brotes de gripe y Análisis de armas contra mantequilla. Naturalmente, crearía dos documentos Rmd y terminaría.
Ahora suponga que llega 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).
Mi solución fue factorizar el proyecto en estos archivos:
dentro de cada archivo Rmd tendría algo como:
El problema aquí es que perdemos reproducibilidad. Mi solución a eso es crear un documento secundario común para incluirlo en cada archivo Rmd. Entonces, al final de cada archivo Rmd que creo, agrego esto:
Y, por supuesto, autodoc.Rmd:
Source Data & Code ---------------------------- <div id="accordion-start"></div> ```{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") } ``` <div id="accordion-stop"></div> <script type="text/javascript"> ```{r jqueryinclude, echo=FALSE, results='asis', warning=FALSE} cat(readLines(url("http://code.jquery.com/jquery-1.9.1.min.js")), sep="\n") ``` </script> <script type="text/javascript"> ```{r tablesorterinclude, echo=FALSE, results='asis', warning=FALSE} cat(readLines(url("http://tablesorter.com/__jquery.tablesorter.js")), sep="\n") ``` </script> <script type="text/javascript"> ```{r jqueryuiinclude, echo=FALSE, results='asis', warning=FALSE} cat(readLines(url("http://code.jquery.com/ui/1.10.2/jquery-ui.min.js")), sep="\n") ``` </script> <script type="text/javascript"> ```{r table2csvinclude, echo=FALSE, results='asis', warning=FALSE} cat(readLines(file.path(jspath, "table2csv.js")), sep="\n") ``` </script> <script type="text/javascript"> $(document).ready(function() { $('tr').has('th').wrap('<thead></thead>'); $('table').each(function() { $('thead', this).prependTo(this); } ); $('table').addClass('tablesorter');$('table').tablesorter();}); //need to put this before the accordion stuff because the panels being hidden makes table2csv return null data $('table.exportable').each(function() {$(this).after('<a download="' + $(this).attr('id') + '.csv" href="data:application/csv;charset=utf-8,'+encodeURIComponent($(this).table2CSV({delivery:'value'}))+'">Download '+$(this).attr('id')+'</a>')}); $('#accordion-start').nextUntil('#accordion-stop').wrapAll("<div id='accordion'></div>"); $('#accordion > h3').each(function() { $(this).nextUntil('h3').wrapAll("<div>"); }); $( '#accordion' ).accordion({ heightStyle: "content", collapsible: true, active: false }); </script>
NB, esto está diseñado para el flujo de trabajo Rmd -> html. Esto será un desastre feo si eliges látex o cualquier otra cosa. Este documento Rmd busca en el entorno global todos los archivos fuente () 'ed 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 archivos de origen. Es un trabajo en progreso, pero no dude en adaptarlo a sus propios usos.
No es de una sola línea, lo sé. Espero que te dé algunas ideas al menos :)
fuente
Probablemente uno debería empezar a pensar diferente. Mi problema es el siguiente: escriba cada código que normalmente habría tenido en un fragmento .Rmd en un archivo .R. Y para el documento Rmd que usa para tejer, es decir, un html, solo le queda
De esta manera probablemente creará un montón 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 investigaciones reproducibles del Sr. Gandrud y me di cuenta de que definitivamente usa 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ápidamente si comienza a hacer todo el análisis en su interior.
fuente
Si está justo después del código, creo que algo así debería funcionar:
readLines
grep
para encontrar los fragmentos de código, buscando líneas que comiencen con<<<
por ejemplowriteLines
Envolver esto en una función debería darle lo que necesita.
fuente
knit('myfile.rmd', tangle=TRUE)
hace en Knitr. Supongo que estoy buscando un trazador de líneas que se enrede y se origine e idealmente no cree archivos.textConnection
para imitar un archivo y obtener la fuente de ese. Esto evitaría la creación de un archivo.textConnection
podría ser el lugar para buscar.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) }
fuente
Yo uso la siguiente función personalizada
source_rmd <- function(rmd_file){ knitr::knit(rmd_file, output = tempfile()) } source_rmd("munge_script.Rmd")
fuente
Prueba la función purl de knitr:
source(knitr::purl("myfile.rmd", quiet=TRUE))
fuente
Recomendaría 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í .
fuente
sys.source ("./ your_script_file_name.R", envir = knitr :: knit_global ())
ponga este comando antes de llamar a las funciones contenidas en your_script_file_name.R.
el "./" que se agrega antes de your_script_file_name.R para mostrar la dirección a su archivo si ya creó un proyecto.
Puede ver este enlace para obtener más detalles: https://bookdown.org/yihui/rmarkdown-cookbook/source-script.html
fuente
esto funcionó para mí
source("myfile.r", echo = TRUE, keep.source = TRUE)
fuente
Yo uso este de una sola línea:
Ver: Mi archivo .Rmd se vuelve muy largo. ¿Es posible dividirlo y generar () sus porciones más pequeñas del .Rmd principal?
fuente