R: source() and path to source files

2020-02-23 21:04发布

There must be something that I don't understand about the source() command in R. I'm still new to it, but I cannot for the life of me understand how it gets its directories from! My problem is this:

I have a wrapper script, wrapper.R, and a source file containing some functions, functions.R. Both of these are in the same directory. If I call source('functions.R') inside the wrapper script, while standing inside the directory where both files are located, everything is fine. However, I want to be able to run my wrapper.R script from some other directory, i.e. not the one where these script are located. If I run my wrapper for another directory, it doesn't work, and I get a cannot open the file error.

I googled and found lots of different threads, but this question seemed to be very clear. The way I understand it, the way I'm doing it should work. Clearly, I'm misunderstanding something. My reading of that thread leads me to believe that source() works on the directory in which the file that calls source() is located in. My reading also leads me to believe that I should not be using chdir = TRUE, as I want to keep the advertised relative directory.

Seeing as it doesn't work... what am I misunderstanding? How can I source files in the same directory as my wrapper script when called from somewhere else?

3条回答
爷的心禁止访问
2楼-- · 2020-02-23 21:37

If you are distributing a script to colleagues, you should really not be writing a script that sources other scripts. What if you want to rename or move functions.R in the future? What if you need to modify a function in functions.R, but wrapper.R relies on the older version of that function? It's a flimsy solution that will cause headache. I would recommend either of the following instead.

  1. Put everything needed into a single, self-contained script and distribute that.

  2. If you really want to separate code into different files, write a package. Might sound like overkill, but packages can actually be very simple and lightweight. In the simplest form a package is just a directory with a DESCRIPTION and NAMESPACE file along with an R/ directory. Hadley breaks this down nicely: http://r-pkgs.had.co.nz/.

查看更多
贼婆χ
3楼-- · 2020-02-23 21:49

You can do this using the here package. It uses the "current working directory at the time when the package is loaded". In other words, the directory you start your R session from.

In your case the code would be:

source(here::here('functions.R'))

This will work even if the wrapper script wrapper.R is in a different directory in the project.

If functions.R is in a subdirectory of the project, just add it to the call to here(), to complete the relative path:

source(here::here('subdirectory', 'functions.R'))
查看更多
虎瘦雄心在
4楼-- · 2020-02-23 21:51

Maybe you can define a helper function in wrapper.R that will try to load other files from the same directory. For example

source_here <- function(x, ...) {
    dir <- "."
    if(sys.nframe()>0) {
        frame <- sys.frame(1)
        if (!is.null(frame$ofile)) {
            dir <- dirname(frame$ofile)
        }
    }
    source(file.path(dir, x), ...)
}

Then you would call

# inside wrapper.R
source_here("functions.R")

Then you would just have source wrapper.R and it will look for functions.R in the same directory.

查看更多
登录 后发表回答