Thanks!

I noticed that there was an almost identical question asked on this list only a few days ago that I completely missed. Sorry for that. Your example and the examples there at least give me a better way to write my function.

Jan


On 19-09-2022 11:58, Achim Zeileis wrote:
On Mon, 19 Sep 2022, Jan van der Laan wrote:


I have a function in which I need to draw some random numbers. However, for some use cases, it is necessary that the same random numbers are drawn (when the input is the same) [1]. So I would like to do a set.seed in my function. This could, however, mess up the seed set by the user. So what I would like to do is store .Random.seed, call set.seed, draw my random numbers and restore .Random.seed to its original value. For an example see the bottom of the mail.

Am I allowed on CRAN to read and restore .Random.seed in a package function? This seems to conflict with the "Packages should not modify the global environment (user’s workspace)." policy. Is there another way to get the same random numbers each time a function is called without messing up the seed set by the user? [2]]

My understanding is that restoring the .Random.seed is exempt from this policy. See the first lines in stats:::simulate.lm for how R itself deals with this situation:

simulate.lm <- function(object, nsim = 1, seed = NULL, ...)
{
     if(!exists(".Random.seed", envir = .GlobalEnv, inherits = FALSE))
         runif(1)                     # initialize the RNG if necessary
     if(is.null(seed))
         RNGstate <- get(".Random.seed", envir = .GlobalEnv)
     else {
         R.seed <- get(".Random.seed", envir = .GlobalEnv)
     set.seed(seed)
         RNGstate <- structure(seed, kind = as.list(RNGkind()))
         on.exit(assign(".Random.seed", R.seed, envir = .GlobalEnv))
     }

[...]


[1] Records are randomly distributed over cluster nodes. For some use cases it is necessary that the same records end up on the same cluster nodes when the function is called multiple times.

[2] A possible solution would be to document that the user should ensure that the same seed is used when calling this function for the use cases where this is needed.


set_seed <- function(seed, ...) {
 if (!exists(".Random.seed")) set.seed(NULL)
 old_seed <- .Random.seed
 if (length(seed) > 1) {
   .Random.seed <<- seed
 } else {
   set.seed(seed, ...)
 }
 invisible(old_seed)
}

foo <- function(n) {
 old_seed <- set_seed(1)
 on.exit(set_seed(old_seed))
 runif(n)
}

Using these:

set.seed(2)
foo(5)
[1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819
runif(5)
[1] 0.1848823 0.7023740 0.5733263 0.1680519 0.9438393
foo(5)
[1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819
runif(5)
[1] 0.9434750 0.1291590 0.8334488 0.4680185 0.5499837

______________________________________________
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel



______________________________________________
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel

Reply via email to