请问R语言怎么设置全局随机数种子?
同一个脚本要产生很多组随机数,怎么保证所有的随机数来自同一组种子?
set.seed只能保证产生的第一组随机数可复现,但再产生第二组时随机数就不同了

不会吧, 可以验证一下, 只要把随机种子设置了以后,后面产生的随机数应该是一样的,比如

rm(list = ls())
set.seed(10)
x = rnorm(10)
y = runif(10,1,4)

x1 = rnorm(10)

    写个函数放进去,这样你只需要在参数里定义一次即可。不过函数内部仍然是每组随机数前面都要设置随机数种子。

    gen_random = function(s = 1024) {
      set.seed(s)
      x = rnorm(10)
      
      set.seed(s)
      y = runif(10, 1, 4)
      
      list(x = x, y = y)
    }

      zaq
      这样肯定是不行的喔,种子数只能保证一次随机数复现。比如这里的X和X1是不一样的。
      rm(list = ls())

      set.seed(10)
      x = rnorm(10)
      y = runif(10,1,4)
      x1 = rnorm(10)
      x
      [1] 0.01874617 -0.18425254 -1.37133055 -0.59916772 0.29454513 0.38979430
      [7] -1.20807618 -0.36367602 -1.62667268 -0.25647839
      x1
      [1] 0.08934727 -0.95494386 -0.19515038 0.92552126 0.48297852 -0.59631064
      [7] -2.18528684 -0.67486594 -2.11906119 -1.26519802

      • zaq 回复了此帖

        chuxinyuan

        谢谢呀我试过这样,但是有没有办法减少写set.seed()这个语句的次数呢。就比如说我只写一次set.seed()就可以保证所有的随机数都来自同一组种子

        xiaohangzi 我又没说 x1 和 x 一样,我只想说,你运行多次,这产生的随机数都是一样的

        我记得随机种子一旦设定了, 后面的随机数都是固定的,因为计算机中的随机数都是伪随机数。eg:

        rm(list = ls())
        set.seed(10)
        x = rnorm(10)
        y = runif(10,1,4)
        
        x1 = rnorm(10)
        
        gen_random = function() {
          x = rnorm(10)
          y = runif(10, 1, 4)
          
          list(x = x, y = y)
        }
        (k1 = gen_random())
        (k2 = gen_random())

        只要你运行上述代码,得到的结果必定如下(下面的 变量名都是独立的,没有任何关系):

        > (x = rnorm(10))
         [1]  0.01874617 -0.18425254 -1.37133055 -0.59916772  0.29454513  0.38979430 -1.20807618 -0.36367602
         [9] -1.62667268 -0.25647839
        > (y = runif(10,1,4))
         [1] 3.594164 2.846057 3.325330 2.066706 2.217550 3.119941 3.514863 1.718767 3.312315 2.067693
        > (x1 = rnorm(10))
         [1]  0.08934727 -0.95494386 -0.19515038  0.92552126  0.48297852 -0.59631064 -2.18528684 -0.67486594
         [9] -2.11906119 -1.26519802
        > (k1 = gen_random())
        $x
         [1] -0.37366156 -0.68755543 -0.87215883 -0.10176101 -0.25378053 -1.85374045 -0.07794607  0.96856634
         [9]  0.18492596 -1.37994358
        
        $y
         [1] 1.226711 2.603280 2.924070 2.577218 1.117844 2.637580 2.118289 3.883907 1.772025 1.623855
        
        > (k2 = gen_random())
        $x
         [1]  1.08655140 -0.76254488 -0.82866254  0.83447390 -0.96765199 -0.02881534  0.23252515 -0.30120868
         [9] -0.67761458  0.65522764
        
        $y
         [1] 2.033031 1.183968 2.106939 2.222781 3.743010 3.666116 3.951197 2.431586 3.080525 2.277239

          zaq
          好的呢,我理解啦。我好像没有表述清楚,就是有没有办法保证X和X1是一样的呢。
          除了在每组随机数前面都设置随机数种子。

          楼主没有描述清楚想要的到底是什么“一致性”导致大家的理解有歧义。对于R而言,随机数产生的时候都是根据种子得到的伪随机数,所以只要一开始的种子确定,后续代码中产生随机数的代码固定,那么整个流程中的随机数就是可重复的。

          楼主的实际需求,是想在每次需要用到某一个随机数的生成的时候都能固定住,那么最直接(甚至本质上也就是唯一的做法)就是每次生成前都设定好种子。

          接下来开始偷懒:

          如果不想敲这么多次set.seed,那么实际上可以做一个封装,在函数里包含set.seed和实际的生成数据的代码,这样可以减少你写set.seed的次数。另外如果是重复进行生成的话那么考虑并行计算的方式,可以用clusterEvalQ函数确保每个并行线程的起始种子是一致的;又或者你的并行本身是采用fork机制的那么天然的起始种子就是一致的。

          不过话说回来我还是感觉楼主的需求没有描述清楚,你所谓的希望每次的种子都一致具体来说到底是想实现什么呢?如果是要跑20个个rnorm(100),还希望每次种子都一致,那干脆直接生成一次,然后复制个20遍就行了?

            fenguoerbian
            谢谢楼主的耐心解答,确实是我没有表述清楚需求,我下次注意。我想生成的随机变量来自不同的分布,例如epsilon<-rnorm(n,0,1),X1<-runif(n,0,1),X23<-mvrnorm(n,rep(0,2),matrix(c(1,0.5,0.5,1),2,2)),我想保证的是epsilon,X1,X23这几个变量的结果可复现。目前我的做法是在每一次生成随机数时都加上set.seed,但我想的是如果想生成的随机变量很多个,如何减少写set.seed次数。
            `> seednum<-666

            set.seed(seednum);epsilon<-rnorm(n,0,1)
            set.seed(seednum);X1<-runif(n,0,1);
            set.seed(seednum);X23<-mvrnorm(n,rep(0,2),matrix(c(1,0.5,0.5,1),2,2))`

            明白楼主的意思了。

            其实问题在于要深入理解一下R里set.seed()的工作原理:想象一个预先生成的随机序列,随机数生成器每次从这个序列头部开始,顺次读取随机数,并输出指定分布的随机数。set.seed()设定种子决定了所取头部的位置。

            此时多个随机数函数顺次执行,生成的多个随机数向量是可重复的。

            但是改变随机数函数执行顺序之后,随机数元序列顺序有变化,导致生成的随机数序列也不同

            比较直观的例子如下, 经过尝试,rnorm生成随机数要消耗两个“元随机数”, runif消耗一个。

            生成6个rnorm和12个runif之后, 新生成的runif(2,0,1) 就一样了。

            set.seed(123)
            
            rnorm(6,0,1)
            #> [1] -0.56047565 -0.23017749  1.55870831  0.07050839  0.12928774  1.71506499
            runif(2,0,1)
            #> [1] 0.6775706 0.5726334
            
            
            set.seed(123)
            
            
            runif(12,0,1)
            #>  [1] 0.2875775 0.7883051 0.4089769 0.8830174 0.9404673 0.0455565 0.5281055
            #>  [8] 0.8924190 0.5514350 0.4566147 0.9568333 0.4533342
            runif(2,0,1)
            #> [1] 0.6775706 0.5726334

            <sup>Created on 2022-06-14 by the reprex package (v2.0.1)</sup>