1

Is it possible to use the set.seed() in a local environment not affecting the following random number generation? It is common use to set the seed in some functions to get reproducible results but I think this is unfortunate as it affects the following generations of random numbers even outside the environment.

Is there any possibility to avoid this behaviour?

set.seed(123)
runif(1) #[1] 0.2875775
runif(1) #[1] 0.7883051
local({
  set.seed(123)
  print(runif(1))
})
#[1] 0.2875775
runif(1) #[1] 0.7883051 (This should not be the second number again)
Cœur
  • 37,241
  • 25
  • 195
  • 267
jakob-r
  • 6,824
  • 3
  • 29
  • 47
  • 2
    I think your example code is missing a `set.seed` in `local`. – Roland Apr 30 '13 at 15:30
  • 2
    Duplicate question? [Setting seed locally not globally in R](http://stackoverflow.com/questions/14324096/setting-seed-locally-not-globally-in-r) – Jason Morgan Apr 30 '13 at 21:56

2 Answers2

2

From ?set.seed:

[If] there is no seed; a new one is created from the current time (and since R 2.14.0, the process ID) when one is required.

set.seed(42)
rnorm(1)
#[1] 1.370958
rm(.Random.seed)
rnorm(1)
#[1] -0.4352643
set.seed(42)
rnorm(1)
#[1] 1.370958
rm(.Random.seed)
rnorm(1)
#[1] -2.338973
Roland
  • 127,288
  • 10
  • 191
  • 288
  • That does not help much as the usual practice is to set a seed in the very beginning of your simulation (or whatever) to get a reproducible result. But may be you have multiple runs of one method which are supposed to be random. Now this method calls a function wich calls `set.seed()`. Now the following random numbers will be the same in each run which is not what I want. Also `rm(.Random.seed)` will lead to non reproducible results. – jakob-r Apr 30 '13 at 16:13
  • I don't understand. Either you want to be reproducible, then you need to use `set.seed`, or you want to be completely random, then you need a random seed. Maybe you want something like `for (i in 1:10) {set.seed(i); rnorm(1)}`? – Roland Apr 30 '13 at 16:21
  • @jakobr If you are doing multiple runs you are either serialising them in a single process so you can do as Roland suggests and set new seeds one after the other, or you will be using parallel computing in which case you could look into the `doRNG` package and `%dorng%` loops. – Simon O'Hanlon Apr 30 '13 at 17:15
0

You can set a seed at the beginning of a function, then reinstate the old seed on exit. Here's a quick demo with a test after the function.

rnorm_seed <- function(n, mean = 0, sd = 1, seed = NULL) {

  if (!is.null(seed)) {
    # reinstate system seed after simulation
    sysSeed <- .GlobalEnv$.Random.seed
    on.exit({
      if (!is.null(sysSeed)) {
        .GlobalEnv$.Random.seed <- sysSeed 
      } else {
        rm(".Random.seed", envir = .GlobalEnv)
      }
    })
    set.seed(seed, kind = "Mersenne-Twister", normal.kind = "Inversion")
  }
  
  rnorm(n, mean, sd)
}

# test
set.seed(8675309)
rnorm(1) # -0.9965824
rnorm(1) #  0.7218241
rnorm(1) # -0.6172088

set.seed(8675309)
rnorm(1) # -0.9965824
rnorm(1) #  0.7218241
rnorm_seed(1, seed = 8675309) # -0.9965824
rnorm(1) # -0.6172088

Lisa DeBruine
  • 818
  • 9
  • 10