问题
你想要保存和回复随机数生成器的状态。
方案
将.Random.seed
保存到其他变量,之后将变量值赋给.Random.seed
从而恢复原来的值。
# 这个例子中,先设定随机数种子
set.seed(423)
runif(3)
#> [1] 0.1089715 0.5973455 0.9726307
# 保存种子
oldseed <- .Random.seed
runif(3)
#> [1] 0.7973768 0.2278427 0.5189830
# 做其他随机数生成相关的事情,比如:
# runif(30)
# ...
# 回复种子
.Random.seed <- oldseed
# 保存种子之后,像之前那样得到相同的随机数
runif(3)
#> [1] 0.7973768 0.2278427 0.5189830
如果你之前还没有在R线程中用过随机数生成器,变量.Random.seed
将会不存在。如果你对此不确定,应当在保存和恢复之前进行检查:
oldseed <- NULL
if (exists(".Random.seed"))
oldseed <- .Random.seed
# 做一些随机数生成操作,比如:
# runif(30)
# ...
if (!is.null(oldseed))
.Random.seed <- oldseed
在函数中保存和恢复随机数生成器的状态
如果你试图在函数中通过使用 .Random.seed <- x
来恢复随机数生成器的状态,结果是行不通的,因为这个操作改变的是名为.Random.seed
的本地变量,而不是全局环境中的这个变量。
这里有两个例子。这些函数想要做的是生成一些随机数,并使得随机数生成器保留未改变的状态。
# 这是个坏的版本
bad_rand_restore <- function() {
if (exists(".Random.seed"))
oldseed <- .Random.seed
else
oldseed <- NULL
print(runif(3))
if (!is.null(oldseed))
.Random.seed <- oldseed
else
rm(".Random.seed")
}
# 这是个好的版本
rand_restore <- function() {
if (exists(".Random.seed", .GlobalEnv))
oldseed <- .GlobalEnv$.Random.seed
else
oldseed <- NULL
print(runif(3))
if (!is.null(oldseed))
.GlobalEnv$.Random.seed <- oldseed
else
rm(".Random.seed", envir = .GlobalEnv)
}
# 坏的版本没有合适地重置随机数生成器状态,因此随机数一直在改变
set.seed(423)
bad_rand_restore()
#> [1] 0.1089715 0.5973455 0.9726307
bad_rand_restore()
#> [1] 0.7973768 0.2278427 0.5189830
bad_rand_restore()
#> [1] 0.6929255 0.8104453 0.1019465
# 好的版本每次都正确地重置了随机数生成器的状态,因此随机数可以保持一致
# stay the same.
set.seed(423)
rand_restore()
#> [1] 0.1089715 0.5973455 0.9726307
rand_restore()
#> [1] 0.1089715 0.5973455 0.9726307
rand_restore()
#> [1] 0.1089715 0.5973455 0.9726307
注意
使用者最好不要修改.Random.seed
变量。