R中set.seed()的作用范围

11

我的 R 脚本调用包含 set.seed() 的子函数。set.seed() 的作用范围是什么?它是否还会影响调用它的主程序?

更具体地说:

# main program
callsubfun()

... some statement ...

sample.int(100,20)



# sub function
callsubfun <- function(x,y,...){
   set.seed(100)
   ... do the work ...
   return(something)
}

1
我非常确定 set.seed() 是“全局的”。它有可能破坏你的伪随机性。 - IRTFM
7
这个测试非常简单易行。你为什么不在发布前先测试一下呢? - Carl Witthoft
4个回答

13

set.seed确实是全局的。但请注意来自?set.seed示例中的内容:

set.seed函数确实具有全局性,但请注意以下来自?set.seed示例的内容:

## If there is no seed, a "random" new one is created:
rm(.Random.seed); runif(1); .Random.seed[1:6]
这意味着您可以在函数结束后或调用函数后调用 rm(.Random.seed, envir=.GlobalEnv) 来将程序的其余部分与函数中的 set.seed 调用分离开来。
要查看这个过程,请在两个不同的R会话中运行以下代码。在两个会话中输出应该是相同的。然后在取消注释rm行的情况下,在两个新的R会话中重新运行代码。现在,您将看到两个新会话中的输出不同,表明函数中对set.seed的调用未将可重复性传递给主程序。
subfun <- function() {
    set.seed(100)
    rnorm(1)
    #rm(.Random.seed, envir=.GlobalEnv)
}

subfun()
#[1] -0.5022

rnorm(1)
# [1] 0.1315

3
以下是您不应这样做的原因:
以下是为什么你不应该这样做的原因:
> set.seed(100)
> rnorm(1)
[1] -0.5021924
> rnorm(1)
[1] 0.1315312

> rand <- function() set.seed(100)
> rand()

> rnorm(1)
[1] -0.5021924   # Ouch!

那么您的意思是,建议只在整个脚本的最顶层使用一次set.seed()函数,对吗?是这样吗? - lolibility
4
是的,确实如此。这是你深思熟虑的问题以及上面的实验所暗示的。事实上,我将建议R-Core在set.seed帮助页面中添加一个警告来说明这一点。我认为该页面上的描述已经暗示了这种行为,但我认为应该更明确地说明其影响。 - IRTFM

-1

set.seed函数为其后的所有代码提供特定的随机状态,但它之前的代码不受影响。以下是一个最小化的示例。

rnorm(1)
#> [1] -0.1020965
set.seed(123)
rnorm(1)
#> [1] -0.5604756
rnorm(1)
#> [1] -0.2301775
rnorm(1)
#> [1] 1.558708

这段代码是使用 reprex package (v0.2.0) 在2018年10月20日创建的。

rnorm(1)
#> [1] 0.4665633
set.seed(123)
rnorm(1)
#> [1] -0.5604756
rnorm(1)
#> [1] -0.2301775
rnorm(1)
#> [1] 1.558708

reprex package (v0.2.0) 创建于2018年10月20日。

  1. 你会发现所有在set.seed之后的代码都被固定在一个给定的随机状态。
  2. 但是,在set.seed之前的代码在两次试验中是不同的,这支持了我的观点。

-2
的回答还可以,但并不总是正确!
您可以使用set.seed()来重现您的算法。也就是说,任何人都可以重现您的结果。
如果您想分享您的代码,我建议您使用set.seed。例如,如果您在stackoverflow上需要帮助,我们可以完全重现您的代码。
set.seed(123)
rand<-rnorm(10)
plot(density(rand))

如果您使用另一个种子,您将获得其他结果

set.seed(234)
rand<-rnorm(10)
plot(density(rand))

两种方法都是正确的,但如果已知起始种子,那么帮助您可能更容易。 顺便说一下,在您的程序中只需使用一次 set.seed,因为您可能会在随机数中生成相关性。我们希望在模拟中得到独立的随机数。


2
这并没有回答问题。问题是在函数内使用set.seed是否会影响整个脚本(全局)? - Rich Scriven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接