[R] Limiting the scope of RNGkind/set.seed

Martin Maechler m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Tue Apr 16 19:22:34 CEST 2019


>>>>> Elizabeth Purdom 
>>>>>     on Tue, 16 Apr 2019 09:45:45 -0700 writes:

    > Hi Bert, Thanks for your response. What you suggest is
    > more or less the fix I suggested in my email (my second
    > version of .rcolors). I writing more because I was
    > wondering if there was a better way to work with RNG that
    > would avoid doing that. It doesn’t feel very friendly for
    > my package to be making changes to the user’s global
    > environment, even though I am setting them back (and if it
    > weren’t for the fact that setting the new R 3.6 argument
    > `sample.kind=“Rounding”` creates a warning, I wouldn’t
    > have even realized I was affecting the user’s settings, so
    > it seems potentially hazardous that packages could be
    > changing users settings without them being aware of
    > it). So I was wondering if there was a way to more fully
    > isolate the command.  Thanks, Elizabeth

Hi Elizabeth,

there's actually something better -- I think -- that you can do:

You store .Random.seed  before doing an RNGkind() & set.seed()
setting, do all that, and make sure that .Random.seed is
restored when leaving your function.

This works because the (typically quite long) .Random.seed
stores the full state of the RNG, i.e., all RNGkind() settings
*and* the result of set.seed() , calling r<foo>(n, ..)  etc.

If you additionally use  on.exit()  instead of manually reset
things, you have the additional advantage, that things are also
reset when your functions ends because the user interrupts its
computations, or an error happens, etc.

So, your function would more elegantly (and robustly!)  look like

.rcolors <- function(seed = 23589) {
    if(!exists(".Random.seed", envir = .GlobalEnv)) {
        message("calling runif(1)"); runif(1) }
    old.R.s <- .Random.seed
    ## will reset everything on exiting this function:
    on.exit(assign(".Random.seed", old.R.s, envir=.GlobalEnv))
    ## set seed for sample() "back compatibly":
    suppressWarnings(RNGversion("3.5.0"))
    set.seed(seed)
    ## return random permutation of "my colors"
    sample(colors()[-c(152:361)])
}

BTW, you can look at  simulate() methods in standard R, e.g.,

  stats:::simulate.lm

to see the same method use [optionally, with slightly more sophistication]


Best,
Martin

Martin Mächler
ETH Zurich, Switzerland



More information about the R-help mailing list