Application of the assign function in loops

7

I want to assign names to variables with a loop. With for I get:

library(tidyverse)

for(i in 1:6){
  names<-str_c('var',i)
  assign(names,runif(30,20,100))
}

But with lapply and map not:

lapply

lapply(1:6,function(i){
  names<-str_c('var',i)
  assign(names,runif(30,20,100))
})

map

map(1:6,function(i){
  names<-str_c('var',i)
  assign(names,runif(30,20,100))
})

Why does this occur? I write the same functions inside the blocks, but only in for the names are assigned.

    
asked by anonymous 14.12.2018 / 19:25

2 answers

8

This happens because assign modifies the parent environment. In the case of for, the parent environment is the global environment itself. So the variables appear to you.

In the case of a function being called by map or lapply , the parent environment is the environment of the calling function itself, and that environment is destroyed shortly after the function is executed.

You can see the environment that the function is using with the environment function:

> for(i in 1:6){
+   names<-str_c('var',i)
+   print(environment())
+   assign(names,runif(30,20,100))
+ }
<environment: R_GlobalEnv>
<environment: R_GlobalEnv>
<environment: R_GlobalEnv>
<environment: R_GlobalEnv>
<environment: R_GlobalEnv>
<environment: R_GlobalEnv>


> lapply(1:6,function(i){
+   names<-str_c('var',i)
+   print(environment())
+   assign(names,runif(30,20,100))
+ })
<environment: 0x14eec3a0>
<environment: 0x2bd9e368>
<environment: 0x13b43ae0>
<environment: 0xe7213c0>
<environment: 0x13dc00d8>
<environment: 0x1a7aab10>

One way to modify lapply or map to work the way you imagine it is to specify the environment for the assign function:

lapply(1:6,function(i){
  names<-str_c('var_lapply_',i)
  assign(names,runif(30,20,100), envir = .GlobalEnv)
})

Note: If you need to use assign you are probably making a code that would look better if you used a named list.

Worth reading the chapter on Advanced R environments: link

    
14.12.2018 / 19:33
6

assign creates new variables in environment of anonymous function, not .GlobalEnv . For this we use the envir argument.

library(tidyverse)

set.seed(1234)
for(i in 1:6){
  names<-str_c('x',i)
  assign(names,runif(30, 20, 100))
}


set.seed(1234)
lapply(1:6, function(i){
  names <- str_c('y', i)
  assign(names, runif(30, 20, 100), envir = .GlobalEnv)
})

identical(x1, y1)
#[1] TRUE

set.seed(1234)
map(1:6, function(i){
  names <- str_c('z', i)
  assign(names, runif(30, 20, 100), envir = .GlobalEnv)
})

identical(x1, z1)
#[1] TRUE
    
14.12.2018 / 19:39