How to source R Markdown file like `source('myfile.r')`?
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.
Source nested R files within Rmarkdown document
The issue you're facing is not related to knitr
or being able to correctly nest the documents but is instead a product of the R project "working directory insanity" one faces asrmarkdown
will knit the document relative to the file directory as opposed to the project root. This leads to different relative paths depending on whether the document is run in the project session or knitr
session.
In addition to the gist, this issue shows a number of workarounds:
knitr specific:
Set a root directory for all chunks to be evaluated relative to rather than the document location.
opts_knit$set(root.dir = '/Users/username/path_to_project')
General case:
Use either rprojroot
or here
(the latter is a wrapper over the former), which uses several criteria to determine the top level directory of your files. You need not be using an RStudio project for this to work.
Any reference to another local file is called using here::here
which will resolve to the same location regardless of the subdirectory in which it's called.
source(here("functions.R"))
source(here("subdirectory", "DataDependency.R"))
source(here("subdirectory2", "furtheranalyis.R"))
This is probably a better solution as it doesn't rely on knitr
options. Alternatively you can set the root.dir
chunk using rprojroot
:
opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())
provided you are using an RStudio project. If not, use rprojroot::find_root
with a specified criterion.
Source code from Rmd file within another Rmd
After some further searching, I've found a solution. There is a package option in knitr that can be set to change the behavior for handling duplicate chunks, appending a number after their label rather than failing with an error. See https://github.com/yihui/knitr/issues/957.
To set this option, use options(knitr.duplicate.label = 'allow')
.
For the sake of completeness, the full code for the function I've written is
source_rmd <- function(file, local = FALSE, ...){
options(knitr.duplicate.label = 'allow')
tempR <- tempfile(tmpdir = ".", fileext = ".R")
on.exit(unlink(tempR))
knitr::purl(file, output=tempR, quiet = TRUE)
envir <- globalenv()
source(tempR, local = envir, ...)
}
Using an R Markdown Document as a source for functions
As was mentioned in the comments, you should probably create a package for this purpose. But if you insist on putting function definitions in scripts and document them using RMarkdown files, using read_chunk()
from the knitr
package might be the way to go.
Note that this approach differs slightly from what you requested. You wanted to have the function definition in the markdown file together with the documentation. And then you wanted to somehow source that file into your R script in order to use the function. I did not find a way to do this (even though it might be possible).
The alternative that I propose puts the function definition in its own R script, say fun.R
. The Rmarkdown file then reads the function definition from fun.R
and adds documentation. If you want to use the function in some other script, you can simply source fun.R
(and not the markdown file). This still means that you have to maintain the code for the function definition only once.
So let me show this with an example. This is fun.R
:
## ---- fun
fun <- function(x) x^2
The first line is an identifier that will be used later. The markdown file is as follows:
---
title: "Documentation of fun()"
output: html_document
---
This documents the function `fun()` defined in `fun.R`.
```{r,cache = FALSE}
knitr::read_chunk("fun.R")
```
This is the function definition
```{r fun}
```
This is an example of how to use `fun()`:
```{r use_fun}
fun(3)
```
The first chunk reads in fun.R
using knitr::read_chunk
. Later on, you can define an empty chunk that has the identifier that was used in fun.R
as its name. This will act as if the contents of fun.R
were written directly in this file. As you see, you can also use fun()
in later chunks. This is a screenshot of the resulting html file:
In a script where you want to use fun()
you simply add source("fun.R")
to source the function definition.
You could also have several functions in a single R file and still document them separately. Simply put an identifier starting with ## ----
before each function definition and then create empty chunks referring to each one of the identifiers.
This is admittedly somewhat more complicated than what you asked for, because it involves two files instead of just one. But at least there is no redundancy
Related Topics
Dynamically Build Call for Lookup Multiple Columns
Center X and Y Axis with Ggplot2
Cannot Install an R Package from Github
Remove Everything After Space in String
What Can R Do About a Messy Data Format
Why Is As.Date Slow on a Character Vector
Using 'Geom_Line()' with X Axis Being Factors
Sparklyr: How to Center a Spark Table Based on Column
Split Delimited Single Value Character Vector
How to Organize Large R Programs
Remove Columns from Dataframe Where Some of Values Are Na
Angle Between Two Vectors in R
Extend Contigency Table with Proportions (Percentages)
Position of the Sun Given Time of Day, Latitude and Longitude
Handling Java.Lang.Outofmemoryerror When Writing to Excel from R