kamiks
kamiks

Reputation: 184

Set a script environement that is different from the global environment

I have a number of loosely related data analysis scripts in R. Some of these scripts have code that removes all variables from the global environment in order to wipe sensitive information after running. Other scripts have variable names that are the same as in other scripts, thereby over-writing critical variables.

I would like to be able to set an entire script / R file, to a separate environment so that its variables and functions are not stored directly in the global environment. I understand that this can be done if the script is called from another script via the source() function; however, is there any way to create an environment within the script itself and have the entire script (thousands of lines) save all of its variables and functions into that environment as opposed to the global environment?

Upvotes: 1

Views: 463

Answers (2)

G. Grothendieck
G. Grothendieck

Reputation: 270428

1) local without saving Enclose your script in local:

local({
  # script goes here
})

The environment will be automatically destroyed when the script exits.

2) local with saving If you want to save the environment then use this instead to save it in .e .

.e <- local({
  # script goes here
  environment()
})

3) search path Another variation if you want to easily access the objects created by the script without having them in the global environment is to convert the environment to a list and put it on the search path. search() can be used to view the search path to verify that it is there. Change the name to whatever you prefer.

local({
  # script goes here
  environment() |> as.list() |> attach(name = "myobjects")
})

Once that is run the objects created can be read by just referring to their name as if they were in the global environment. To remove the list from the search path, destroying it, use detach("myobjects") .

Upvotes: 2

Allan Cameron
Allan Cameron

Reputation: 174606

If you are using multiple scripts repeatedly in R in this way, it is better to organize your scripts into functions, and build a package with these functions. This keeps your R code in reusable blocks that are easy to load and keeps your global workspace clean.

However, I realize that this may be easier said than done if you have many separate scripts that are very long and complex.

One way to get around the problem is to wrap your code in its own environment. For example, if you put

with(new.env(), {

at the top of your script, and

})

at the end, your script will run in its own environment.

For example:

rm(list = ls())

with(new.env(), {
 
 # Start of original script code

 a <- 1
 b <- 2
 print(a + b)
 
 # End of script code

 })
#> [1] 3

Where we can see the global environment remains empty:

ls()
#> character(0)

If you want to be able to access the variables produced in the script after it has complete, you could instead run:

script1 <- new.env()
with(script1, {
 
 # Start of original script code

 a <- 1
 b <- 2
 print(a + b)
 
 # End of script code
 
 })
#> [1] 3

Now we have a single object in the global workspace called script1:

ls()
#> [1] "script1"

And we can access its contents using the $ operator:

script1$a
#> [1] 1

Created on 2021-11-01 by the reprex package (v2.0.0)

Upvotes: 4

Related Questions