r – Applying the `assign` function in loops

Question:

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

library(tidyverse)

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

But not with lapply and map :

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 outside the names for assigned.

Answer:

This happens because assign modifies the parent environment. In the case of for, the parent environment is the global environment itself. That's why 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 this environment is destroyed shortly after the function is executed.


You can see the environment 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 think 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 are needing to use assign you are probably writing code that would look better if you used a named list.

It is worth reading the chapter on Advanced R environments: https://adv-r.hadley.nz/environments.html

Scroll to Top