Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to source R Markdown file like `source('myfile.r')`?

Tags:

markdown

r

knitr

I often have a main R Markdown file or knitr LaTeX file where I source some other R file (e.g., for data processing). However, I was thinking that in some instances it would be beneficial to have these sourced files be their own reproducible documents (e.g., an R Markdown file that not only includes commands for data processing but also produces a reproducible document that explains the data processing decisions).

Thus, I would like to have a command like source('myfile.rmd') in my main R Markdown file. that would extract and source all the R code inside the R code chunks of myfile.rmd. Of course, this gives rise to an error.

The following command works:

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

where results='hide' could be omitted if the output was desired. I.e., knitr outputs the R code from myfile.rmd into myfile.R.

However, it doesn't seem perfect:

  • it results in the creation of an extra file
  • it needs to appear in its own code chunk if control over the display is required.
  • It's not as elegant as simple source(...).

Thus my question: Is there a more elegant way of sourcing the R code of an R Markdown file?

like image 892
Jeromy Anglim Avatar asked Jun 10 '12 03:06

Jeromy Anglim


People also ask

Can you source an R Markdown file?

To share R code like function definitions, you can put this code in an R script and import it in each file with the function source() To share common R Markdown text and code chunks, you can use child documents.

How do you source a file in RStudio?

Begin typing the name of the file you want to navigate to; when it appears, select it and press Enter. When a document is open in a source window, RStudio will jump to that window whenever you navigate to the document, or to a symbol in the document.

How do I retrieve data from R Markdown?

You can click in the upper left menu File > Import Dataset > From Excel and select the file to import it. Then you can copy the code that appears in the R console with the code required for import the data in xlsx and then copy it in a R Markdown code chunk.

How do I run a Markdown file in R?

To open a new file, click File > New File > R Markdown in the RStudio menu bar. A window will pop up that helps you build the YAML frontmatter for the . Rmd file. Use the radio buttons to select the specific type of output that you wish to build.


2 Answers

It seems you are looking for a one-liner. How about putting this in your .Rprofile?

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

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

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

like image 95
Yihui Xie Avatar answered Sep 20 '22 21:09

Yihui Xie


Factor the common code out into a separate R file, and then source that R file into each Rmd file you want it in.

so for example let's say I have two reports I need to make, Flu Outbreaks and Guns vs Butter Analysis. Naturally I'd create two Rmd documents and be done with it.

Now suppose boss comes along and wants to see the variations of Flu Outbreaks versus Butter prices (controlling for 9mm ammo).

  • Copying and pasting the code to analyze the reports into the new report is a bad idea for code reuse, etc.
  • I want it to look nice.

My solution was to factor the project into these files:

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

within each Rmd file I'd have something like:

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

The problem here is that we lose reproducibility. My solution to that is to create a common child document to include into each Rmd file. So at the end of every Rmd file I create, I add this:

```{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> 

N.B., this is designed for the Rmd -> html workflow. This will be an ugly mess if you go with latex or anything else. This Rmd document looks through the global environment for all the source()'ed files and includes their source at the end of your document. It includes jquery ui, tablesorter, and sets the document up to use an accordion style to show/hide sourced files. It's a work in progress, but feel free to adapt it to your own uses.

Not a one-liner, I know. Hope it gives you some ideas at least :)

like image 44
Keith Twombley Avatar answered Sep 21 '22 21:09

Keith Twombley