0Pricing
R Academy · Lesson

Generating Random Distributions

Sample from normal, uniform, binomial, and Poisson distributions.

Generating Random Distributions is a free R Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

R's Distribution Functions

R provides four functions for each distribution: r (random), d (density), p (cumulative probability), q (quantile). The r* functions generate random samples.

# Pattern: r<dist>(n, param1, param2, ...)
# d<dist>(x, ...) -> density/probability
# p<dist>(q, ...) -> cumulative probability
# q<dist>(p, ...) -> quantile

# Example with normal distribution:
rnorm(5, mean = 0, sd = 1)    # 5 random draws
dnorm(0, mean = 0, sd = 1)    # density at x=0
pnorm(1.96, mean = 0, sd = 1) # P(X <= 1.96)
qnorm(0.975, mean = 0, sd = 1) # z-score for 97.5%
cat('Four functions: r, d, p, q for each distribution')

rnorm(): Normal Distribution

rnorm(n, mean, sd) generates n samples from N(mean, sd²). The default is the standard normal N(0,1). The normal distribution is the workhorse of statistics — central limit theorem guarantees its prevalence.

set.seed(42)
# Standard normal (mean=0, sd=1)
z_scores <- rnorm(1000)
mean(z_scores)  # ~0
sd(z_scores)    # ~1

# Custom normal (IQ scores: mean=100, sd=15)
set.seed(42)
iq_scores <- rnorm(100, mean = 100, sd = 15)
mean(iq_scores)  # ~100
sd(iq_scores)    # ~15
summary(iq_scores)

# About 68% within 1 sd
mean(abs(iq_scores - 100) < 15)  # ~0.68

runif(): Uniform Distribution

runif(n, min, max) generates n samples uniformly distributed between min and max. All values in the range are equally likely. Default: runif(n) gives values in [0, 1].

set.seed(7)
# Default: uniform on [0, 1]
u <- runif(5)
print(u)  # values in (0, 1)

# Uniform on [a, b]
temps <- runif(100, min = -10, max = 40)  # temperatures
mean(temps)   # ~15 (midpoint)
range(temps)  # should be within [-10, 40]

# Discrete simulation using floor()
dice_rolls <- floor(runif(10, min = 1, max = 7))
print(dice_rolls)  # integers 1-6
table(floor(runif(600, 1, 7)))  # roughly equal counts

rbinom(): Binomial Distribution

rbinom(n, size, prob) simulates n binomial experiments, each consisting of size Bernoulli trials with success probability prob. Use size=1 for Bernoulli draws.

set.seed(123)
# 10 coin flips (prob=0.5), repeated 5 times
coin_flips <- rbinom(5, size = 10, prob = 0.5)
print(coin_flips)  # number of heads each time

# Bernoulli: single flip (size=1)
flips <- rbinom(20, size = 1, prob = 0.5)
print(flips)  # 0s and 1s
mean(flips)   # ~0.5

# Biased coin (prob=0.7)
biased <- rbinom(1000, size = 1, prob = 0.7)
mean(biased)  # ~0.7

# Many trials: normal approximation kicks in
hundred_flips <- rbinom(1000, size = 100, prob = 0.5)
mean(hundred_flips)  # ~50

rpois(): Poisson Distribution

rpois(n, lambda) generates n samples from a Poisson distribution with rate λ. Models count data (events per interval): website visits per minute, defects per unit, calls per hour.

set.seed(5)
# Calls received per hour (average 3)
calls <- rpois(24, lambda = 3)  # 24 hours
print(calls)  # integers, mostly 1-6
mean(calls)   # ~3 (expectation = lambda)
var(calls)    # ~3 (variance = lambda for Poisson)

# Count the distribution
table(calls)

# Rare events (lambda=0.5)
rare_events <- rpois(100, lambda = 0.5)
table(rare_events)  # mostly 0s and 1s
mean(rare_events)   # ~0.5

rexp(): Exponential Distribution

rexp(n, rate) generates n samples from the exponential distribution with specified rate. Models time between events (inter-arrival times). Mean = 1/rate. Memoryless property.

set.seed(42)
# Time between customer arrivals (rate=2 per minute)
# Mean wait time = 1/2 = 0.5 minutes
arrival_times <- rexp(100, rate = 2)
mean(arrival_times)  # ~0.5
sd(arrival_times)    # ~0.5 (mean = sd for exponential)

# Simulate a queue
cumulative_arrivals <- cumsum(rexp(10, rate = 3))
print(round(cumulative_arrivals, 3))

# Exponential CDF: P(X <= x) = 1 - exp(-rate*x)
pexp(0.5, rate = 2)   # P(wait <= 0.5 min)
mean(arrival_times <= 0.5)  # empirical estimate

sample(): Discrete Sampling

sample(x, size, replace) draws size elements from vector x. replace=FALSE (default) is sampling without replacement; replace=TRUE allows repeated values.

set.seed(10)
# Sample without replacement (like drawing cards)
cards <- 1:52
hand <- sample(cards, size = 5, replace = FALSE)
print(hand)  # 5 unique cards

# Sample with replacement (bootstrap)
x <- c(10, 20, 30, 40, 50)
bootstrap_sample <- sample(x, size = 5, replace = TRUE)
print(bootstrap_sample)  # may have repeats

# Simulate rolling two dice 1000 times
dice <- function() sum(sample(1:6, 2, replace = TRUE))
rolls <- replicate(1000, dice())
table(rolls) / 1000  # empirical probabilities

Weighted Sampling

sample(x, size, replace, prob) uses probability weights. The prob vector assigns relative probabilities to each element — useful for non-uniform discrete distributions.

set.seed(99)
# Loaded die: 6 is twice as likely
faces <- 1:6
weights <- c(1, 1, 1, 1, 1, 2)  # relative
norm_weights <- weights / sum(weights)

rolls <- sample(faces, size = 1000, replace = TRUE,
                prob = norm_weights)
table(rolls) / 1000
# 6 appears ~2/7 ~= 0.286 of the time

# Categorical sampling
categories <- c('A', 'B', 'C')
probs <- c(0.5, 0.3, 0.2)
sample(categories, 10, replace = TRUE, prob = probs)

rgeom() and rnbinom(): Count Distributions

rgeom(n, prob) counts failures before first success. rnbinom(n, size, prob) counts failures before size successes. Both model overdispersed count data (more variance than Poisson).

set.seed(42)
# Geometric: flips until first head (prob=0.3)
# Number of FAILURES before first success
flips_until_head <- rgeom(10, prob = 0.3) + 1  # +1 for the success
print(flips_until_head)
mean(flips_until_head)  # ~1/0.3 = 3.33

# Negative binomial: overdispersed count data
# e.g., number of parasites per host
counts <- rnbinom(100, size = 2, prob = 0.4)
mean(counts)   # ~3 (theoretical: size*(1-p)/p)
var(counts)    # much larger than mean -> overdispersed

# Compare variance to Poisson with same mean
pois_counts <- rpois(100, lambda = mean(counts))
var(counts) / var(pois_counts)  # > 1

rt() and rf(): t and F Distributions

rt(n, df) generates t-distributed samples with df degrees of freedom. As df → ∞ it converges to normal. rf(n, df1, df2) generates F-distributed samples — the ratio of chi-squared variables.

set.seed(1)
# t distribution: heavier tails than normal
t_vals <- rt(1000, df = 5)
mean(t_vals)  # ~0
sd(t_vals)    # > 1 (inflated by heavy tails)

# Compare to normal
n_vals <- rnorm(1000)
# t has more extreme values (heavy tails)
sum(abs(t_vals) > 3)   # e.g., ~30
sum(abs(n_vals) > 3)   # e.g., ~3

# F distribution: used in ANOVA F-tests
f_vals <- rf(1000, df1 = 5, df2 = 20)
range(f_vals)   # always positive
mean(f_vals)    # ~df2/(df2-2) = 20/18 = 1.11

Visualizing Random Distributions

Histograms and density plots visualize the shape of simulated distributions. Compare empirical density to theoretical density curves using hist() with curve(dnorm(...)) overlay.

set.seed(42)
x <- rnorm(10000, mean = 5, sd = 2)

# Quick summary statistics
summary(x)
cat('Mean:', mean(x), '\n')
cat('SD:', sd(x), '\n')
cat('Skewness (should be ~0 for normal):',
    mean(((x - mean(x))/sd(x))^3), '\n')

# Empirical quantiles vs theoretical
quantile(x, c(0.025, 0.25, 0.5, 0.75, 0.975))
# Compare to theoretical:
qnorm(c(0.025, 0.25, 0.5, 0.75, 0.975),
      mean = 5, sd = 2)

Quick Check

Test your knowledge of R's random distribution functions.

Recap: Random Distributions

Key takeaways: rnorm(n, mean, sd) for normal; runif(n, min, max) for uniform; rbinom(n, size, prob) for binomial; rpois(n, lambda) for Poisson counts; rexp(n, rate) for exponential waiting times; sample(x, size, replace) for discrete sampling. Always use set.seed() before generating random numbers in reproducible analyses.

set.seed(42)
# Quick reference of common distributions:
rnorm(3, mean = 0, sd = 1)        # Normal
runif(3, min = 0, max = 1)        # Uniform
rbinom(3, size = 10, prob = 0.5)  # Binomial
rpois(3, lambda = 3)              # Poisson
rexp(3, rate = 1)                 # Exponential
rt(3, df = 10)                    # Student t
rf(3, df1 = 5, df2 = 20)          # F distribution
rgeom(3, prob = 0.3)              # Geometric
sample(1:10, 3, replace = TRUE)   # Discrete uniform
cat('R has 20+ built-in distributions')

Frequently asked questions

Is the “Generating Random Distributions” lesson free?

Yes — the full text of “Generating Random Distributions” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.

What will I learn in “Generating Random Distributions”?

Sample from normal, uniform, binomial, and Poisson distributions. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start R Academy?

No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Generating Random Distributions” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this R Academy lesson?

Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. set.seed() and Reproducibility
  2. Generating Random Distributions
  3. Monte Carlo Simulation Basics
  4. Bootstrap Resampling in R
← Back to R Academy