8

It seem %>% in the magrittr package is not working for the function load(). This is my minimal example to reproduce my question.

## Create two example variables and save to tempdir()
a <- 1
b <- 1

save(list = ls(), file = file.path(tempdir(), 'tmp.RData'))

## Remove all variables and load into global environment
# rm(list = ls())

load(file.path(tempdir(), 'tmp.RData'))
ls()
# [1] "a" "b"

# Write the same code with pipe "%>%", but not variable is loaded
# rm(list =ls())
library(magrittr)

tempdir() %>% file.path('tmp.RData') %>% load
ls()
# character(0)

I don't understand why the pipe is not working for load(). Thanks for any suggestions.

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
Bangyou
  • 9,462
  • 16
  • 62
  • 94

1 Answers1

7

The envir argument in load() needs to be specified as either globalenv() or parent.frame(3).

# in a fresh R session ...
a <- 1
b <- 1
save(list = ls(), file = file.path(tempdir(), 'tmp.RData'))

# in another fresh session ...
ls()
# character(0)
tempdir() %>% file.path("tmp.RData") %>% load(envir = globalenv())
ls()
# [1] "a" "b"

The following also works:

tempdir() %>% file.path("tmp.RData") %>% load(envir = parent.frame(3))

I'll try to explain why. When you call load() from any environment, the function loads the new objects in the parent environment.

Now, the global environment globalenv() is your R workspace. So, if you call load from the global environment (i.e. the workspace) everything works as you expect. Visualise this:

  • Global environment
    • load()

However, if you call load() from inside a function, then you've inserted an environment in between load and the global environment. Visualise this:

  • Global environment
    • function
      • load()

This is exactly what happens when you put %>% into the mix:

  • Global environment
    • %>%
      • load()

There are two solutions for resolving this. Either explicitly point to globalenv() or walk 3 steps up the chain to the global environment using parent.frame(3).


Note: There was an issue reported on GitHub for this. Not sure what the resolution was, or if there is one yet. The issue was just reported in September.

Many thanks to @Andrie for improving this explanation.

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • Thanks for your suggestion. It is working for global environment, but still need to fix it when calling "load" in a function. – Bangyou Nov 21 '14 at 05:09
  • Thanks for your suggestion. For my digging, pipe truly evaluate the function load and load all variable into the new environment. But the returned values are invisible (visible=FALSE), so pipe return an invisible result (invisible(result[["value"]])). Not sure how to fix it. – Bangyou Nov 21 '14 at 05:50
  • See detail in the comment of github: https://github.com/smbache/magrittr/issues/38 – Bangyou Nov 21 '14 at 05:56
  • @Andrie Thanks for your explanation. It does make sense to me. And parent.frame(3) still works when calling load inside custom functions. – Bangyou Nov 21 '14 at 10:21
  • @Bangyou Just note that `parent.frame(3)` will only work if the global environment is 3 frames up the chain. If you embed the function in another, then that number is going to increment. – Andrie Nov 21 '14 at 10:23
  • @Andrie I have test it inside functions and it works. See my testing codes here: http://pastebin.com/UbXt3CnJ – Bangyou Nov 21 '14 at 10:26
  • @Bangyou Be careful. It's not a good idea. It's better to explicitly specify the environment you want. – Andrie Nov 21 '14 at 10:28
  • @Andrie Yes it is a bad idea. I just test the idea. – Bangyou Nov 21 '14 at 10:29