Written and maintained by CASRAI Editorial Board
Last updated
Random number generation in R means drawing pseudo-random values with functions such as runif(), rnorm() and sample(). Call set.seed() first and the same script returns the same values every time. R’s current default is the Mersenne-Twister generator, and since R 3.6.0 the default way sample() turns random bits into integers has changed, so a seed alone does not guarantee a result that matches an older script.
What it is used for in research
Researchers generate random numbers in R to draw random samples from a sampling frame, to assign participants or units to arms of a study, to run simulations and bootstrap resamples, and to initialise algorithms such as k-means. The values are produced by a deterministic algorithm, so they are pseudo-random: the sequence is fully determined by the generator and its starting state, which is exactly what makes a seeded analysis replicable.
Related CASRAI pages cover the surrounding methods: simple random sampling, Monte Carlo simulation, bootstrapping in R, and the dictionary entry on randomization methods in clinical trials.
Install or access (official source only)
Everything on this page is in base R: the base package supplies set.seed(), RNGkind(), RNGversion() and sample(), and the stats package supplies runif() and rnorm(). Both load automatically when R starts, so no extra package is required. R itself is obtained from the Comprehensive R Archive Network (CRAN) at cran.r-project.org. The official reference pages are listed in the Sources section below.
Step-by-step: generating random numbers in R
1. Set the seed
- Call
set.seed(123)once, near the top of the script. The seed is a single value that R interprets as an integer. - Run the random draws that follow. Re-running from the
set.seed()line reproduces them.
set.seed(123)
2. Draw uniform random numbers with runif()
The signature is runif(n, min = 0, max = 1). It returns n values spread evenly between min and max.
set.seed(123)
u <- runif(5) # five values between 0 and 1
v <- runif(5, min = 10, max = 20)
3. Draw normal random numbers with rnorm()
The signature is rnorm(n, mean = 0, sd = 1). The documentation describes it as generating random deviates from the normal distribution; the algorithm used is the one selected by the normal.kind setting (default "Inversion").
set.seed(123)
z <- rnorm(100) # standard normal
x <- rnorm(100, mean = 50, sd = 10) # mean 50, SD 10
4. Sample from your own data with sample()
The signature is sample(x, size, replace = FALSE, prob = NULL). A companion, sample.int(n, size = n, replace = FALSE, prob = NULL), draws integer indices from 1 to n.
set.seed(123)
ids <- 1:200
sample(ids, 20) # 20 IDs without replacement
sample(c('A', 'B'), 50, replace = TRUE)
sample(c('control', 'treatment'), 10, replace = TRUE, prob = c(0.5, 0.5))
The prob weights must be non-negative and not all zero, but they do not need to sum to 1.
Reproducible random numbers with set.seed
Three details decide whether a collaborator, or you in a year, gets the same numbers from the same script.
- State the generator, not just the seed. The R documentation advises using
set.seed(), ideally with an explicitkindandnormal.kind. For example:set.seed(123, kind = 'Mersenne-Twister', normal.kind = 'Inversion', sample.kind = 'Rejection'). Those three values are the current defaults. - Know the R 3.6.0 change.
sample.kind = 'Rejection'is the default now; before R 3.6.0 the default was'Rounding', which is kept only so that old results can be reproduced. A script written before 3.6.0 that callssample()can therefore return different samples under a modern R even with the same seed.RNGversion('3.5.3')switches the generators back to the defaults of that earlier version for that purpose. - Do not edit
.Random.seed. R stores the generator state in an integer vector named.Random.seed. The documentation says users should not alter it; useset.seed()instead.set.seed(NULL)re-initialises the generator as if no seed had been set.
For reporting, record the seed value, the R version and the RNGkind() output alongside the analysis. This supports the kind of computational reproducibility that reviewers and replicators ask for.
Output and how to read it
runif()andrnorm()return a numeric vector of lengthn. Each call advances the generator’s state, so two successive calls after oneset.seed()give different numbers. To repeat a draw, callset.seed()again with the same value first.sample()returns elements ofx, not positions, unless you usesample.int()or sample fromseq_along(x).- Run
RNGkind()with no arguments to see the three active settings (generator, normal generator, sample method), andRNGkind('Mersenne-Twister')style calls to change them. - A different seed gives a different but equally valid draw. If a conclusion changes with the seed, the simulation needs more replicates; do not choose the seed that gives the preferred answer.
Troubleshooting
sample() on one number draws from 1 to that number
If x is a single number of 1 or more, sample(x) samples from 1:x, not from x. This bites when a filter such as x[x > 9] happens to keep exactly one value. Guard it with x[sample.int(length(x), 1)] or sample(seq_along(x), 1) and index back into x.
Results differ from an older script or another machine
Check, in order: the seed value, the R version, RNGkind() output, and whether the script was written before R 3.6.0 (see the sample.kind change above). Also check that the order of random calls has not changed, because inserting one extra runif() call shifts every later draw.
Invalid prob argument
Weights in prob must be non-negative and not all zero.
Free alternatives
R is free, and so are the other generators built into it. RNGkind() lets you choose among these generator kinds, documented in the base R manual:
| RNGkind option | Note from the documentation |
|---|---|
| Mersenne-Twister | The default generator |
| Wichmann-Hill | Available through RNGkind() |
| Marsaglia-Multicarry | Available through RNGkind() |
| Super-Duper | Available through RNGkind() |
| Knuth-TAOCP-2002 | Available through RNGkind() |
| Knuth-TAOCP | Available through RNGkind() |
| L’Ecuyer-CMRG | Available through RNGkind() |
| user-supplied | A generator you provide yourself |
If you work in a spreadsheet rather than R, the CASRAI guide to generating random numbers in Excel covers that route.
FAQ
How do I generate a random number in R?
Call runif(1) for one uniform value between 0 and 1, rnorm(1) for one standard normal value, or sample(1:10, 1) for one integer from 1 to 10. Add set.seed() before the call if you need the result to be repeatable.
What does set.seed() do in R?
It initialises the random number generator from a single integer-valued seed, so the sequence of draws that follows is the same each time. set.seed(NULL) re-initialises as if no seed had been set.
What is R’s default random number generator?
The Mersenne-Twister, with "Inversion" for normal deviates and "Rejection" as the sample method.
Why does my old script give a different sample in a new R?
R 3.6.0 changed the default sample.kind from "Rounding" to "Rejection". Use RNGversion() or set sample.kind = 'Rounding' only to reproduce legacy results.
Should I save or edit .Random.seed?
Do not alter it. Use set.seed() and report the seed value in your methods.
Sources (official docs)
- R-devel manual, base package, Random Number Generation (
set.seed,RNGkind,RNGversion,.Random.seed), stat.ethz.ch/R-manual/R-devel/library/base/html/Random.html (checked 29 October 2026). - R-devel manual, stats package, The Normal Distribution (
rnorm), stat.ethz.ch/R-manual/R-devel/library/stats/html/Normal.html (checked 29 October 2026). - R-devel manual, stats package, The Uniform Distribution (
runif), stat.ethz.ch/R-manual/R-devel/library/stats/html/Uniform.html (checked 29 October 2026). - R-devel manual, base package, Random Samples and Permutations (
sample,sample.int), stat.ethz.ch/R-manual/R-devel/library/base/html/sample.html (checked 29 October 2026).








