Limiting the scope of RNGkind/set.seed

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Limiting the scope of RNGkind/set.seed

Elizabeth Purdom-2
Hello,

I have a package, and inside of it I have a small function that selects a random palette of colors for graphing purposes. It’s a large number of colors, which is why I don’t manually select them, but I did want them to stay constant so I set the seed before doing so. So I had a little function in my package that does this:

.rcolors<-function(){
        set.seed(23589)
        x<-sample(colors()[-c(152:361)])
        return(x)
}
massivePalette<-unique(c(bigPalette,.rcolors()))

Now that the sample function has been changed in R 3.6, I would need to use `sample.kind=“Rounding”` to get the same set of colors as I had previously. However, I don’t want to do that in my package, because that appears to change the global environment sampling:

> RNGkind()
[1] "Mersenne-Twister" "Inversion"        "Rejection"      
> RNGkind(sample.kind="Rejection")
> x<-clusterExperiment:::.rcolors() #now I have changed the function so that sample.kind=“Rounding” — I’ve suppressed the warnings
> RNGkind()
[1] "Mersenne-Twister" "Inversion"        "Rounding”  

So I could do something like this:

.rcolors<-function(){
        currentRNG<-RNGkind()
        suppressWarnings(RNGkind(sample.kind="Rounding"))
        set.seed(23589)
        x<-sample(colors()[-c(152:361)])
        #set it back to default
        suppressWarnings(RNGkind(sample.kind=currentRNG[3]))
        return(x)
}

But is there a way to change the random sampling in the function environment and not change it in the global environment? (For this function, I can just break down and accept that I will have different colors from this point on, but I’d like to know more generally; especially since it means that my `fixed` colors are not really fixed since they depend on the user’s setting of random sampling techniques, which I hadn’t considered before).

All of the best,
Elizabeth Purdom

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Limiting the scope of RNGkind/set.seed

Bert Gunter-2
I think I'm missing something. Why does something like this not do what you
want:

> RNGkind()
[1] "Mersenne-Twister" "Inversion"
> f <- function(){
+    cur <- RNGkind(NULL)[1]
+    RNGkind("Super-Duper")
+    print(RNGkind())
+    RNGkind(cur)
+ }
> f()
[1] "Super-Duper" "Inversion"
> RNGkind()
[1] "Mersenne-Twister" "Inversion"

Cheers,
Bert

Bert Gunter

"The trouble with having an open mind is that people keep coming along and
sticking things into it."
-- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )


On Tue, Apr 16, 2019 at 9:13 AM Elizabeth Purdom <[hidden email]>
wrote:

> Hello,
>
> I have a package, and inside of it I have a small function that selects a
> random palette of colors for graphing purposes. It’s a large number of
> colors, which is why I don’t manually select them, but I did want them to
> stay constant so I set the seed before doing so. So I had a little function
> in my package that does this:
>
> .rcolors<-function(){
>         set.seed(23589)
>         x<-sample(colors()[-c(152:361)])
>         return(x)
> }
> massivePalette<-unique(c(bigPalette,.rcolors()))
>
> Now that the sample function has been changed in R 3.6, I would need to
> use `sample.kind=“Rounding”` to get the same set of colors as I had
> previously. However, I don’t want to do that in my package, because that
> appears to change the global environment sampling:
>
> > RNGkind()
> [1] "Mersenne-Twister" "Inversion"        "Rejection"
> > RNGkind(sample.kind="Rejection")
> > x<-clusterExperiment:::.rcolors() #now I have changed the function so
> that sample.kind=“Rounding” — I’ve suppressed the warnings
> > RNGkind()
> [1] "Mersenne-Twister" "Inversion"        "Rounding”
>
> So I could do something like this:
>
> .rcolors<-function(){
>         currentRNG<-RNGkind()
>         suppressWarnings(RNGkind(sample.kind="Rounding"))
>         set.seed(23589)
>         x<-sample(colors()[-c(152:361)])
>         #set it back to default
>         suppressWarnings(RNGkind(sample.kind=currentRNG[3]))
>         return(x)
> }
>
> But is there a way to change the random sampling in the function
> environment and not change it in the global environment? (For this
> function, I can just break down and accept that I will have different
> colors from this point on, but I’d like to know more generally; especially
> since it means that my `fixed` colors are not really fixed since they
> depend on the user’s setting of random sampling techniques, which I hadn’t
> considered before).
>
> All of the best,
> Elizabeth Purdom
>
> ______________________________________________
> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Limiting the scope of RNGkind/set.seed

Elizabeth Purdom-2
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

> On Apr 16, 2019, at 9:36 AM, Bert Gunter <[hidden email]> wrote:
>
> I think I'm missing something. Why does something like this not do what you want:
>
> > RNGkind()
> [1] "Mersenne-Twister" "Inversion"      
> > f <- function(){
> +    cur <- RNGkind(NULL)[1]
> +    RNGkind("Super-Duper")
> +    print(RNGkind())
> +    RNGkind(cur)
> + }
> > f()
> [1] "Super-Duper" "Inversion"  
> > RNGkind()
> [1] "Mersenne-Twister" "Inversion"
>
> Cheers,
> Bert
>
> Bert Gunter
>
> "The trouble with having an open mind is that people keep coming along and sticking things into it."
> -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )
>
>
> On Tue, Apr 16, 2019 at 9:13 AM Elizabeth Purdom <[hidden email] <mailto:[hidden email]>> wrote:
> Hello,
>
> I have a package, and inside of it I have a small function that selects a random palette of colors for graphing purposes. It’s a large number of colors, which is why I don’t manually select them, but I did want them to stay constant so I set the seed before doing so. So I had a little function in my package that does this:
>
> .rcolors<-function(){
>         set.seed(23589)
>         x<-sample(colors()[-c(152:361)])
>         return(x)
> }
> massivePalette<-unique(c(bigPalette,.rcolors()))
>
> Now that the sample function has been changed in R 3.6, I would need to use `sample.kind=“Rounding”` to get the same set of colors as I had previously. However, I don’t want to do that in my package, because that appears to change the global environment sampling:
>
> > RNGkind()
> [1] "Mersenne-Twister" "Inversion"        "Rejection"      
> > RNGkind(sample.kind="Rejection")
> > x<-clusterExperiment:::.rcolors() #now I have changed the function so that sample.kind=“Rounding” — I’ve suppressed the warnings
> > RNGkind()
> [1] "Mersenne-Twister" "Inversion"        "Rounding”  
>
> So I could do something like this:
>
> .rcolors<-function(){
>         currentRNG<-RNGkind()
>         suppressWarnings(RNGkind(sample.kind="Rounding"))
>         set.seed(23589)
>         x<-sample(colors()[-c(152:361)])
>         #set it back to default
>         suppressWarnings(RNGkind(sample.kind=currentRNG[3]))
>         return(x)
> }
>
> But is there a way to change the random sampling in the function environment and not change it in the global environment? (For this function, I can just break down and accept that I will have different colors from this point on, but I’d like to know more generally; especially since it means that my `fixed` colors are not really fixed since they depend on the user’s setting of random sampling techniques, which I hadn’t considered before).
>
> All of the best,
> Elizabeth Purdom
>
> ______________________________________________
> [hidden email] <mailto:[hidden email]> mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help <https://stat.ethz.ch/mailman/listinfo/r-help>
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html <http://www.r-project.org/posting-guide.html>
> and provide commented, minimal, self-contained, reproducible code.


        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Limiting the scope of RNGkind/set.seed

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

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Limiting the scope of RNGkind/set.seed

Paul Gilbert-2
In reply to this post by Elizabeth Purdom-2
Elizabeth

There is a package (of mine) setRNG on CRAN that may be a helpful
example (code/tests/examples/vignette). Most of the package is testing
designed to fail if the RNG in R is changed in a way that will affect my
other package testing. Martin's function in the previous reply has most
of the import parts and adds warning suppression, so you might want to
consider small adjustments on a combination of the two. Just to
summarize the issues, from memory:

0/ Using a preset default seed in a function's argument makes the
function not random by default. If you are doing that then maybe you
need to consider carefully whether the function should be using random
number generation.

1/ It is good practice to use on.exit() in your function to reset
things, so the state remains unaltered if your function fails.

2/ Saving the old seed does not work when it is unset, as it is by
default in a new session, so you need to do something that insures it is
set.

3/ You may need to save and reset not only the seed but also the RNG
kind and the normal.kind, and possibly the kind for some other
distributions. (setRNG does not handle other distributions.) It looks
like you need to save and reset sample.kind.

4/ You should add the capability to pass all settings to your functions
so that you can reproduce things when you want.

5/ I have found it useful to always pass back the settings in objects
returned by functions like simulations. That way you always have a
record when you discover something you want to reproduce.

6/ If parallel computing is considered then for reproducibility you need
to save the number of nodes in the cluster. (I think this point is not
as widely known as it should be.)

No doubt I have forgotten a few things.

Paul Gilbert

On 4/17/19 6:00 AM, [hidden email] wrote:
 > Date: Tue, 16 Apr 2019 19:22:34 +0200
 > From: Martin Maechler<[hidden email]>
 > To: Elizabeth Purdom<[hidden email]>
 > Cc: Bert Gunter<[hidden email]>, R-help
 >     <[hidden email]>
 > Subject: Re: [R] Limiting the scope of RNGkind/set.seed
 > Message-ID:<[hidden email]>
 > Content-Type: text/plain; charset="utf-8"
 >
 >>>>>> 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

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Limiting the scope of RNGkind/set.seed

Elizabeth Purdom-2
In reply to this post by Martin Maechler
Thanks Martin, this seems much better. All of the best, Elizabeth

> On Apr 16, 2019, at 10:22 AM, Martin Maechler <[hidden email]> wrote:
>
>>>>>> 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

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.