Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Source script to separate environment in R, not the global environment

Is there a way to source() a script in R such that it is attached as a parent to the global environment (.GlobalEnv)?

Currently, when I source a script, all variables and functions of that script appear in my global (interactive) environment. I'd like to include these variables and functions in the search path, but not in .GlobalEnv. That is, I'd like the sourced script to behave like an attached package, which gets attached between the global and base environments (see figure from Advanced R Environments)

enter image description here

like image 529
Megatron Avatar asked Sep 21 '16 15:09

Megatron


2 Answers

The following environment insertion appears to achieve the desired functionality:

Check the current search path:

search()
# [1] ".GlobalEnv"        "package:stats"     "package:graphics"
# [4] "package:grDevices" "package:utils"     "package:datasets"
# [7] "package:methods"   "Autoloads"         "package:base"

Add new environment for sourced packages and use local parameter when source()ing:

myEnv <- new.env()    
source("some_other_script.R", local=myEnv)
attach(myEnv, name="sourced_scripts")

Check the search path:

search()
#  [1] ".GlobalEnv"        "sourced_scripts"   "package:dplyr"
#  [4] "package:stats"     "package:graphics"  "package:grDevices"
#  [7] "package:utils"     "package:datasets"  "package:methods"
# [10] "Autoloads"         "package:base"

Note that we attach() the new environment after sourcing, so that dplyr is attached after our script environment in the search path.

like image 92
Megatron Avatar answered Sep 19 '22 08:09

Megatron


The simplest way to source a script as if it was a package (i.e. such that lexical scoping won't result in the use of variables defined in the global environment when calling functions defined in your R script) is to create an environment that that is whose parent is the .BaseNamespaceEnv, and then call source() using that environment.

For example if you have a script like this:

# << my-script.R >>
my_fun <- function(x){x + y}

Then evaluating the following at the console, won't generate an error, as it would if my_fun were defined within it's own package:

source("my-script.R")
y = 2
my_fun(1)
#> 3

However, if you create an environment whose search() path does not include the Global Environment (.GlobalEnv) then you'll get a proper error when you call the function from your script:

# Create the environment:
ENV = new.env(parent = .BaseNamespaceEnv)
# Attache it to the search path so that objects in your environment can be
# found from the global environment (i.e. from the console):
attach(ENV)
# do things:
source("my-script.R",ENV)
y = 2
my_fun(1)
#> Error in .ENV$my_fun(3) : object 'y' not found
like image 38
Jthorpe Avatar answered Sep 19 '22 08:09

Jthorpe