How to include (source) R script in other scripts

I created an R script utility, util.R, which I want to use from other scripts in my project. What is the correct way to ensure that the function that this script defines is available to work in my other scripts?

I am looking for something similar to the require function, which only downloads a package if it is not already loaded. I do not want to call source("util.R") , because it will load the script every time it is called.

I know that I will get some answers telling me to create a package, as in Organize source code R : But I am not creating something that will be used elsewhere, it's just a stand-alone project.

+80
r
Jun 23 2018-11-11T00:
source share
5 answers

Here is one possible way. Use the exists function to check for something unique in the util.R code.

For example:

 if(!exists("foo", mode="function")) source("util.R") 

(Edited to include mode="function" , as Gavin Simpson pointed out)

+73
Jun 23 '11 at 15:30
source share

There is no such built-in thing, since R does not track calls to source and cannot determine what was downloaded from this place (this is not the case when you use packages). However, you can use the same idea as in C .h files, i.e. Wrap the integer in:

 if(!exists('util_R')){ util_R<-T #Code } 
+15
Jun 23 2018-11-11T00:
source share

Say util.R produces the function foo() . You can check if this function is available in the global environment and the source of the script if it is not:

 if(identical(length(ls(pattern = "^foo$")), 0)) source("util.R") 

This will find something called foo . If you want to find a function, then (as @Andrie mentioned) exists() is useful, but you need to tell exactly what type of object to look for, for example.

 if(exists("foo", mode = "function")) source("util.R") 

Here exists() in action:

 > exists("foo", mode = "function") [1] FALSE > foo <- function(x) x > exists("foo", mode = "function") [1] TRUE > rm(foo) > foo <- 1:10 > exists("foo", mode = "function") [1] FALSE 
+8
Jun 23 2018-11-11T00:
source share

You can write a function that takes a file name and an environment name, checks to see if the file has been uploaded to the environment and uses sys.source for the source, if not.

Here's a quick and untested feature (improvements are welcome!):

 include <- function(file, env) { # ensure file and env are provided if(missing(file) || missing(env)) stop("'file' and 'env' must be provided") # ensure env is character if(!is.character(file) || !is.character(env)) stop("'file' and 'env' must be a character") # see if env is attached to the search path if(env %in% search()) { ENV <- get(env) files <- get(".files",ENV) # if the file hasn't been loaded if(!(file %in% files)) { sys.source(file, ENV) # load the file assign(".files", c(file, files), envir=ENV) # set the flag } } else { ENV <- attach(NULL, name=env) # create/attach new environment sys.source(file, ENV) # load the file assign(".files", file, envir=ENV) # set the flag } } 
+4
Jun 23 '11 at 19:28
source share

Here is the function I wrote. It wraps the base::source function to store a list of sources in a global environment list called sourced . It will only redirect the file if you provide the argument .force=TRUE to call the source. Its argument signature is otherwise identical to the real source() , so you don't have to rewrite your scripts to use this.

 warning("overriding source with my own function FYI") source <- function(path, .force=FALSE, ...) { library(tools) path <- tryCatch(normalizePath(path), error=function(e) path) m<-md5sum(path) go<-TRUE if (!is.vector(.GlobalEnv$sourced)) { .GlobalEnv$sourced <- list() } if(! is.null(.GlobalEnv$sourced[[path]])) { if(m == .GlobalEnv$sourced[[path]]) { message(sprintf("Not re-sourcing %s. Override with:\n source('%s', .force=TRUE)", path, path)) go<-FALSE } else { message(sprintf('re-sourcing %s as it has changed from: %s to: %s', path, .GlobalEnv$sourced[[path]], m)) go<-TRUE } } if(.force) { go<-TRUE message(" ...forcing.") } if(go) { message(sprintf("sourcing %s", path)) .GlobalEnv$sourced[path] <- m base::source(path, ...) } } 

This is pretty talkative (lots of message() calls), so you can take these lines if you like it. Any advice from R veteran users is welcome; I am new to R.

+3
May 16 '13 at 17:16
source share



All Articles