Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get R's lapply (and mclapply) to restore the state of the random number generator?

R ignores setting .Random.seed inside of an lapply. Using set.seed however, works fine.

Some code:

# I can save the state of the RNG for a few seeds
seed.list <- lapply( 1:5, function(x) {
                        set.seed(x)
                        seed.state <- .Random.seed
                        print( rnorm(1) )
                        return( seed.state )}) 
#[1] -0.6264538
#[1] -0.8969145
#[1] -0.9619334

# But I get different numbers if I try to restore 
# the state of the RNG inside of an lapply
tmp.rest.state <-  lapply(1:5, function(x) { 
                        .Random.seed <- seed.list[[x]]
                        print(rnorm(1))})
# [1] -0.2925257
# [1] 0.2587882
# [1] -1.152132

# lapply is just ignoring the assignment of .Random.seed
.Random.seed <- seed.list[[3]]
print( rnorm(1) ) # The last printed value from seed.list
# [1] -0.9619334
print( rnorm(1) ) # The first value in tmp.rest.state
# [1] -0.2925257

My goal is to checkpoint MCMC runs so that they can be resumed exactly. I can easily save the state of the RNG, I just can't get R to load it inside of an lapply loop!

Is there a way to force R to notice setting .Random.seed? Or is there a simpler way to make this happen?

In case it matters, I'm using 64 bit R:

R version 2.15.1 (2012-06-22) -- "Roasted Marshmallows"
Platform: x86_64-pc-linux-gnu (64-bit)

On Ubuntu 12.04 LTS:

nathanvan@nathanvan-N61Jq:~$ uname -a
Linux nathanvan-N61Jq 3.2.0-26-generic #41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
like image 221
Nathan VanHoudnos Avatar asked Jul 07 '12 19:07

Nathan VanHoudnos


1 Answers

This happens because .Random.seed is evaluated as a local object inside your call to lapply.

You need to assign the value of .Random.seed in the global environment:

tmp.rest.state <- lapply(seed.list, function(x) {
    assign(".Random.seed", x, envir=globalenv())
    print(rnorm(1))
  }
)

[1] -0.6264538
[1] -0.8969145
[1] -0.9619334
[1] 0.2167549
[1] -0.8408555

The reason your code doesn't work is that .Random.seed get assigned in the environment of the anonymous function in lapply, but rnorm() looks for .Random.seed in the global environment.


For the record, here is my first attempt, which will only work in some situations:

Here is one way to fix it, by using <<-. (Yes, I know this is frowned upon, but possibly justified. An alternative would be to use eval() and force evaluation in a calling environment.

tmp.rest.state <- lapply(seed.list, function(x) {
    .Random.seed <<- x
    print(rnorm(1))
  }
)

[1] -0.6264538
[1] -0.8969145
[1] -0.9619334
[1] 0.2167549
[1] -0.8408555

Note that this solution will not work if your lapply() is nested in another function, since <<- only evaluates in the parent environment, not the global environment.

like image 133
Andrie Avatar answered Sep 18 '22 12:09

Andrie