How to fix R Markdown file, for example `source ('myfile.r')`?

I often have the main R Markdown file or LaTeX file, where I source some other R file (for example, for data processing). However, I thought that in some cases it would be useful for these source files to be their own playable documents (for example, the R Markdown file, which not only includes data processing commands, but also creates a playable document that explains the data processing solutions).

Thus, I would like to have a command like source('myfile.rmd') in my main R Markdown file. which will extract and output all R code inside the R code fragments myfile.rmd . Of course, this leads to an error.

The following command works:

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

where results='hide' may be omitted if output was desired. Ie, knitr outputs the R code from myfile.rmd to myfile.R .

However, this does not seem ideal:

  • this leads to the creation of an additional file
  • it should appear in it own code fragment if control over display is required.
  • It is not as elegant as just source(...) .

So my question is: Is there a more elegant way to find the R-code of an R Markdown file?

+73
r markdown knitr
Jun 10 2018-12-12T00:
source share
7 answers

It seems you are looking for a single line. How to put this in your .Rprofile ?

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

However, I do not understand why you want the source() code in the Rmd file itself. I mean that knit() will run all the code in this document, and if you extract the code and run it in a piece, all the code will run twice when you knit() this document (you run yourself inside). These two tasks should be separate.

If you really want to run all the code, RStudio made it pretty easy: Ctrl + Shift + R It basically calls purl() and source() behind the scenes.

+30
Jun 10 '12 at 15:44
source share

Encode the common code into a separate R file, and then send this R file to each Rmd file you want.

so, for example, let's say I have two reports that I need to do, “Flu Outbreaks” and “Guns” versus “Oil Analysis”. Naturally, I would create two Rmd documents and do away with them.

Now suppose the boss comes in and wants to see price variations for flu versus oil (control over 9mm ammunition).

  • Copying and pasting code to analyze reports in a new report is a bad idea to reuse code, etc.
  • I want it to look beautiful.

My solution was to include the project in these files:

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

in each Rmd file I will have something like:

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

The problem is that we are losing reproducibility. My solution is to create a common child document for inclusion in each Rmd file. So at the end of every Rmd file I create, I add the following:

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

And of course 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, it is intended for the workflow Rmd → html. It will be an ugly mess if you go with latex or something else. This Rmd document looks at the global environment for all ed () source files and includes their source at the end of your document. It includes jquery ui, tablesorter and sets the document to use the accordion style to show / hide the source files. This is a work in progress, but feel free to adapt it to your own needs.

I do not know a single liner. Hope this gives you some ideas :)

+18
May 31 '13 at 13:40
source share

Probably need to start thinking differently. My problem is this: Write each code that you would normally have in a .Rmd block in a .R file. And for the Rmd document that you use for knitting, i.e. Html, you only left

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

That way, you will probably create a bunch of .R files and you will lose the advantage of processing all the "chunk after chunk" code with ctrl + alt + n (or + c, but this usually doesn't work). But I read a book on Mr. Gandrud's reproducible research and realized that he definitely uses the knitr and .Rmd files exclusively to create html files. The core analysis itself is a .R file. I think .Rmd documents are growing too fast if you start all your analysis inside.

+3
Apr 29 '15 at 7:07
source share

If you are only after the code, I think something along these lines should work:

  • Read markdown / R file with readLines
  • Use grep to find code snippets looking for lines starting with <<< , for example
  • Take a subset of the object that contains the source lines to get only the code
  • Dump this temporary file using writeLines
  • Send this file to your R session

Wrapping this in a function should give you what you need.

+2
Jun 10 2018-12-12T00:
source share

The following hack worked fine for me:

 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) } 
+2
Oct 19 '16 at 20:40
source share

I would recommend storing the main analysis and calculation code in a .R file and import the pieces as needed into the .Rmd file. I explained the process here .

+1
May 19 '16 at 10:44 p.m.
source share

I am using the following custom function

 source_rmd <- function(rmd_file){ knitr::knit(rmd_file, output = tempfile()) } source_rmd("munge_script.Rmd") 
+1
Aug 30 '19 at 22:11
source share



All Articles