Skip to main content
v2026.11,858 entries · CC-BY 4.0

Random Number Generation in R: set.seed, rnorm, runif, sample

How to generate random numbers in R with runif, rnorm and sample, and make them reproducible with set.seed, RNGkind and the R 3.6.0 sampling change.

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

  1. Call set.seed(123) once, near the top of the script. The seed is a single value that R interprets as an integer.
  2. 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 explicit kind and normal.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 calls sample() 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; use set.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() and rnorm() return a numeric vector of length n. Each call advances the generator’s state, so two successive calls after one set.seed() give different numbers. To repeat a draw, call set.seed() again with the same value first.
  • sample() returns elements of x, not positions, unless you use sample.int() or sample from seq_along(x).
  • Run RNGkind() with no arguments to see the three active settings (generator, normal generator, sample method), and RNGkind('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)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Random Number Generation in R: set.seed, rnorm, runif, sample

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.