rguides

sample()

sample(x, size, replace = FALSE, prob = NULL)

The sample() function randomly selects elements from a vector. It is essential for simulations, bootstrap resampling, creating train/test splits for machine learning, and randomizing order. By default, it performs sampling without replacement, meaning each element can only be selected once.

Syntax

sample(x, size, replace = FALSE, prob = NULL)

Parameters

ParameterTypeDefaultDescription
xvector,A vector from which to sample
sizeinteger,Number of elements to sample; must not exceed length of x unless replace = TRUE
replacelogicalFALSEIf TRUE, elements can be sampled multiple times
probnumeric vectorNULLA vector of probabilities for sampling each element; must sum to 1

Examples

Basic usage

# Sample 3 elements from a vector without replacement
sample(1:10, 3)
# [1] 4 2 9

# Sample with replacement (allows repeats)
sample(1:3, 10, replace = TRUE)
# [1] 1 3 1 2 1 3 2 1 1 2

When you call sample(x) without specifying size, it returns a random permutation of all elements — effectively shuffling the entire vector. This default behavior works because size defaults to length(x). Shuffling is useful for randomizing row order before cross-validation splits, creating randomized experimental designs, or generating permutations for Monte Carlo tests where the null distribution is constructed by permuting observed data.

Randomizing vector order

# Shuffle a vector by sampling all elements
x <- c("a", "b", "c", "d", "e")
sample(x)
# [1] "c" "a" "e" "d" "b"

# Equivalent to sample(x, length(x))
sample(x)
# [1] "b" "d" "a" "e" "c"

You can control selection probabilities via the prob argument, which accepts a vector of non-negative weights. By default every element has equal probability, but weighted sampling lets you model unequal outcome likelihoods — for instance, simulating a biased coin flip or drawing from a discrete distribution where some categories are rarer than others. The probabilities do not need to sum to one because sample() normalizes them internally, so passing raw frequency counts as weights also works correctly.

Weighted sampling

# Sample with custom probabilities
sample(c("low", "medium", "high"), 1000, 
       replace = TRUE, 
       prob = c(0.5, 0.3, 0.2))

table(sample(c("low", "medium", "high"), 1000, 
             replace = TRUE, 
             prob = c(0.5, 0.3, 0.2)))
#    high     low  medium 
#     196     491     313

Common patterns

Beyond basic element selection, sample() is a building block for several routine data-science tasks. A common use is splitting a dataset into training and test partitions — sample() draws the row indices for the training set, and the remaining indices form the test set. This approach avoids ordering biases that arise from a simple sequential split and is the basis for holdout validation in predictive modeling workflows.

Train/test split: Randomly partition data into training and testing sets.

set.seed(42)
data <- data.frame(x = 1:100, y = rnorm(100))

indices <- sample(nrow(data), size = 0.8 * nrow(data))
train <- data[indices, ]
test <- data[-indices, ]

nrow(train)  # 80
nrow(test)   # 20

Bootstrap resampling draws repeated samples with replacement from the original data to estimate the sampling distribution of a statistic. Each bootstrap replicate is the same size as the original dataset, obtained by calling sample(n, replace = TRUE), and the statistic of interest is recomputed on each replicate. The core idea is that the observed sample approximates the population, so resampling from it mimics drawing new samples from the population.

set.seed(123)
original <- c(10, 20, 30, 40, 50)

# Create 3 bootstrap samples
bootstrap_samples <- replicate(3, sample(original, replace = TRUE))
bootstrap_samples
#      [,1] [,2] [,3]
# [1,]   40   20   40
# [2,]   40   50   20
# [3,]   20   30   10
# [4,]   10   40   50
# [5,]   50   10   30

Random password generation uses sample() to draw characters from a defined alphabet. By combining lowercase letters, uppercase letters, and digits into a single character vector, you can sample n characters with replacement and collapse them into a string with paste(..., collapse = ""). This pattern is also useful for generating random IDs, coupon codes, or temporary file names where uniqueness matters more than cryptographic strength.

chars <- c(letters, LETTERS, 0:9)
set.seed(42)
password <- paste0(sample(chars, 8, replace = TRUE), collapse = "")
password
# [1] "xK7Pm3nQ"

sample() in practice

sample() is the foundation for simulation, resampling, and randomization in R. Its two main uses are: drawing a random sample from a vector without replacement (sample(x, n)) and shuffling a vector (sample(x) or sample(x, length(x))). Setting replace = TRUE enables bootstrap resampling, where each draw is independent and an element can appear multiple times.

The prob argument allows weighted sampling: sample(c("A","B","C"), size=100, replace=TRUE, prob=c(0.5, 0.3, 0.2)) samples according to specified probabilities. The probabilities do not need to sum to 1, they are normalized internally. This makes sample() directly usable for discrete distributions in simulation.

For reproducibility, always set a seed before sample() with set.seed(). The same seed produces the same sequence on the same platform and R version. Between major R versions, the default random-number generator changed in R 3.6 (sample.kind="Rounding" vs "Rejection"), so code that depends on specific random output should document the R version and seed together.

sample.int(n, size, replace) is a faster low-level function for sampling integers from 1 to n. It avoids the overhead of constructing the input vector, which matters when n is large. sample.int(1e9, 100) samples 100 integers from 1 to one billion without allocating a billion-element vector.

sample() draws without replacement by default. Set replace = TRUE for bootstrap sampling. When x is a single integer, sample(n) generates a random permutation of 1:n. Pass a prob vector to weight the sampling probabilities — probabilities do not need to sum to 1; they are normalized internally. For reproducible results, call set.seed() before sample().

sample() with a single integer argument n generates a random permutation of 1:n. With a vector x, it draws size elements at random. The replace argument defaults to FALSE (sampling without replacement); set replace = TRUE for bootstrap resampling where the same element can be drawn more than once.

The prob argument accepts a vector of weights proportional to selection probability. The weights do not need to sum to 1 — they are normalized internally. sample(x, size, replace = FALSE, prob = c(0.1, 0.9)) makes the second element nine times more likely than the first.

For reproducible results, call set.seed(n) before sample(). The seed is global state; in parallel code, use parallel::clusterSetRNGStream() or the future package’s RNG tools to manage seeds across workers.

sample.int(n, size, replace, prob) is a slightly faster variant when sampling from 1:n because it avoids coercing a vector. It is used internally by many simulation functions.

See also