R: sourcing files using a relative path
Asked Answered
C

1

70

Sourcing files using a relative path is useful when dealing with large codebases. Other programming languages have well-defined mechanisms for sourcing files using a path relative to the directory of the file being sourced into. An example is Ruby's require_relative. What is a good way to implement relative path sourcing in R?

Below is what I pieced together a while back using various recipes and R forum posts. It's worked well for me for straight development but is not robust. For example, it breaks when the files are loaded via the testthat library, specifically auto_test(). rscript_stack() returns character(0).

# Returns the stack of RScript files
rscript_stack <- function() {
  Filter(Negate(is.null), lapply(sys.frames(), function(x) x$ofile))
}

# Returns the current RScript file path
rscript_current <- function() {
  stack <- rscript_stack()
  r <- as.character(stack[length(stack)])
  first_char <- substring(r, 1, 1)
  if (first_char != '~' && first_char != .Platform$file.sep) {
    r <- file.path(getwd(), r)
  }
  r
}

# Sources relative to the current script
source_relative <- function(relative_path, ...) {
  source(file.path(dirname(rscript_current()), relative_path), ...)
}

Do you know of a better source_relative implementation?

Candelaria answered 21/8, 2012 at 4:26 Comment(2)
Is the rscript_stack doing exactly what is described in the answers to this question? #1816106 ... or perhaps this one: #8088243Centerpiece
You are absolutely right. In fact, I recall reading @Hadley's answer to #1816106 and using the code. Ironic that it is testthat that the code doesn't work with.Candelaria
C
80

After a discussion with @hadley on GitHub, I realized that my question goes against the common development patterns in R.

It seems that in R files that are sourced often assume that the working directory (getwd()) is set to the directory they are in. To make this work, source has a chdir argument whose default value is FALSE. When set to TRUE, it will change the working directory to the directory of the file being sourced.

In summary:

  1. Assume that source is always relative because the working directory of the file being sourced is set to the directory where the file is.

  2. To make this work, always set chdir=T when you source files from another directory, e.g., source('lib/stats/big_stats.R', chdir=T).

For convenient sourcing of entire directories in a predictable way I wrote sourceDir, which sources files in a directory in alphabetical order.

sourceDir <- function (path, pattern = "\\.[rR]$", env = NULL, chdir = TRUE) 
{
    files <- sort(dir(path, pattern, full.names = TRUE))
    lapply(files, source, chdir = chdir)
}
Candelaria answered 2/9, 2012 at 6:54 Comment(1)
@DanChaltiel: `read.csv(./) I guess that is what you're looking forChopping

© 2022 - 2024 — McMap. All rights reserved.