Saving the state of the random number generator

Table of contents

Problem

You want to save and restore the state of the random number generator

Solution

Save .Random.seed to another variable.

# For this example, set the random seed
set.seed(423)
runif(3)
# 0.1089715 0.5973455 0.9726307

# Save the seed
oldseed <- .Random.seed

runif(3)
# 0.7973768 0.2278427 0.5189830

# Do some other stuff with RNG here, such as:
# runif(30)
# ...


# Restore the seed
.Random.seed <- oldseed

# Get the same random numbers as before, after saving the seed
runif(3)
# 0.7973768 0.2278427 0.5189830

If no random number generator has been used in your R session, the variable .Random.seed will not exist. If you cannot be certain that an RNG has been used before attempting to save, the seed, you should check for it before saving and restoring:

oldseed <- NULL
if (exists(".Random.seed"))  oldseed <- .Random.seed

# Do some other stuff with RNG here, such as:
# runif(30)
# ...


if (!is.null(oldseed))
    .Random.seed <- oldseed

Saving and restoring the state of the RNG in functions

If you attempt to restore the state of the random number generator within a function by using .Random.seed <- x, it will not work, because this operation changes a local variable named .Random.seed, instead of the variable in the global envrionment.

Here are two examples. What these functions are supposed to do is generate some random numbers, while leaving the state of the RNG unchanged.

# This is the bad version
bad_rand_restore <- function() {
    if (exists(".Random.seed"))  oldseed <- .Random.seed
    print(runif(3))
    if (exists(".Random.seed"))  .Random.seed <- oldseed
}


# This is the good version
rand_restore <- function() {
    if (exists(".Random.seed"))  oldseed <- get(".Random.seed", .GlobalEnv)
    print(runif(3))
    if (exists(".Random.seed"))  assign(".Random.seed", oldseed, .GlobalEnv)
}


# The bad version changes the RNG state, so random numbers keep changing
set.seed(423)
bad_rand_restore()
# 0.1089715 0.5973455 0.9726307
bad_rand_restore()
# 0.7973768 0.2278427 0.5189830
bad_rand_restore()
# 0.6929255 0.8104453 0.1019465

# The good version doesn't alter the RNG state, so random numbers stay the same
set.seed(423)
rand_restore()
# 0.1089715 0.5973455 0.9726307
rand_restore()
# 0.1089715 0.5973455 0.9726307
rand_restore()
# 0.1089715 0.5973455 0.9726307

Notes

.Random.seed should not be modified by the user.