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

Solution 1:

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.

Solution 2:

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 :)

Solution 3:

Try the purl function from knitr:

source(knitr::purl("myfile.rmd", quiet=TRUE))