How to use source() in a .Rmd file when accessing code from multiple folders?

70 Views Asked by At

I've started to explore calling and reusing code snippets in various .Rmd projects. I'm running into issues though with the working directory not being able to access the correct files.

Take this file structure, for instance:

R/
├─ code/
│  ├─ compile_data.R
├─ my_functions/
│  ├─ function_01.R
├─ report/
│  ├─ report.Rmd

When running the report.Rmd file I have an option to recompile the underlying data with compile_data.R as such:

recompile <- TRUE

if (recompile == TRUE) {
  source("../code/compile_data.R")
}

This call works as expected, but fails when compile_data.R script tries to call a custom function via

source('R/my_functionfunctions/function_01.R')

I'm assuming I need to change my working directory somewhere but not sure where to do it so that I can access the code files from anywhere without breaking the sub-calls to other scripts.

2

There are 2 best solutions below

0
Robert Schauner On

One way to get rid of these types of errors, besides making a package as some of the comments recommended is to use a package called here. In practice it would look like this:

report.rmd

recompile <- TRUE

if (recompile == TRUE) {
  source(here("code/compile_data.R"))
}

compile_data.R

source(here('my_functions/function_01.R'))

Bonus because you no longer need to setwd().

Why I like here: When you have a complicated project with multiple folders where your scripts are, worrying about the working directory gets complicated. Being able to reference everything from your project directory helps make your code more readable (no paths like ../../main_folder/random_script.R) and more portable (because you get rid of paths like ~/directory/stuct/specific_to_computer). I think these benefits outweigh the addition of a dependency.

Bonus 2: you can also build a path like this here("directory", "dir2", "file.R")

0
Eyayaw On

Your rmd file should compile from your working directory, R/.

When you source from code, everything should run without path problems. Edit the line in compile_data.R to source('../my_functions/function_01.R') instead.

In case you need to switch to a different directory during knitting, you can use a custom function like the one below:

# taken from adv-r 1st ed http://adv-r.had.co.nz/Functions.html#return-values
in_dir <- function(dir, code) {
  old = setwd(dir)
  on.exit(setwd(old))
  force(code)
}

```{r}
recompile = TRUE

if (recompile) {
  in_dir("code/", source("compile_data.R"))
}
```