Application of the `assign` function in loops

Asked

Viewed 214 times

5

I want to play names in variables with a loop. With for I can get:

library(tidyverse)

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

But with lapply and map nay:

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 happen? I write the same functions inside the blocks, but only in for the assignment of names is made.

2 answers

6


This happens because the assign modifies the parent environment. In the case of the parent environment, the parent environment is the global environment itself. That’s why variables appear to you.

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


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

> 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>

A way to modify the lapply or the map to work the way you imagine is to specify Environment for the function assign:

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 is probably making a code that would look better if it used a named list.

Read the Advanced R Nvironments chapter: https://adv-r.hadley.nz/environments.html

  • What the code would look like with lapply and map, then?

4

The assign creates new variables in the environment of the anonymous function, not .GlobalEnv. That’s what the argument’s for envir.

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.