R Programming Quiz: Random Sampling
10 questions · exam conditions
0:00
Random SamplingQuestion 1 of 10

Consider the R code u <- runif(100, min = -2, max = 5); y <- 3 - 2 * u.

Which expression directly generates 100 values having the same distribution as y?

runif(100, min = -7, max = 7)
runif(100, min = -7, max = 13)
runif(100, min = -1, max = 13)
runif(100, min = -4, max = 10)
← Back to quizzes

R Programming Quiz

R Programming Quiz: Random Sampling

Practice Random Sampling in R Programming with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.

What this quiz covers

This quiz focuses on Random Sampling, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.

How to use this quiz

Try each quiz question before looking at the correct answer. Use the explanations to review missed ideas, then come back to similar questions until the pattern feels familiar.

All questions

Question 1

Consider the R code u <- runif(100, min = -2, max = 5); y <- 3 - 2 * u.

Which expression directly generates 100 values having the same distribution as y?

  1. runif(100, min = -7, max = 7) (correct answer)
  2. runif(100, min = -7, max = 13)
  3. runif(100, min = -1, max = 13)
  4. runif(100, min = -4, max = 10)
Explanation: When a uniform random variable is transformed linearly, you need to track how the transformation shifts and rescales the distribution's endpoints — not just its mean. Here, u ~ Uniform(-2, 5), and y = 3 - 2u. To find the distribution of y, apply the transformation to each endpoint of u. Because the coefficient on u is negative (-2), the transformation flips the interval: ymin=32(5)=310=7y_{\min} = 3 - 2(5) = 3 - 10 = -7 ymax=32(2)=3+4=7y_{\max} = 3 - 2(-2) = 3 + 4 = 7 So y ~ Uniform(-7, 7), which is exactly what A generates: runif(100, min = -7, max = 13) — wait, that's B. A gives runif(100, min = -7, max = 7), confirming it's correct. B (min = -7, max = 13) gets the minimum right but miscalculates the maximum — likely by using 3+2(5)=133 + 2(5) = 13 instead of 32(2)3 - 2(-2), forgetting the sign flip. C (min = -1, max = 13) appears to come from applying the transformation without distributing the negative: treating it as 3+2u3 + 2u instead of 32u3 - 2u, giving wrong values at both endpoints. D (min = -4, max = 10) seems to reflect a scaling error, perhaps halving or otherwise misapplying the multiplier. Strategy tip: When transforming a + b*u where b < 0, always flip which endpoint becomes the min and which becomes the max. Plug both original endpoints into the full expression and compare — never assume the original minimum maps to the new minimum.

Question 2

A programmer must use runif() to generate n independent integers, with each integer from 44 through 99 having equal probability.

Which expression implements the required sampling?

  1. ceiling(runif(n, min = 4, max = 9))
  2. floor(runif(n, min = 4, max = 9))
  3. round(runif(n, min = 4, max = 9))
  4. floor(runif(n, min = 4, max = 10)) (correct answer)
Explanation: When converting a continuous uniform distribution to discrete integers, you need to think carefully about two things: which rounding function you use, and what range you pass to runif(). These choices interact, and getting either one wrong will silently exclude values from your sample. runif(n, min = a, max = b) generates values on the continuous interval [a,b)[a, b). To turn those into integers, you need a function that maps each integer to an equally-sized "slice" of that interval. floor() does exactly this — it rounds down, so every value in [k,k+1)[k, k+1) maps to integer kk. For your target integers 4,5,6,7,8,94, 5, 6, 7, 8, 9 (six values), you need six unit-length slices, meaning the interval must span [4,10)[4, 10). That makes Dfloor(runif(n, min = 4, max = 10)) — the correct answer. A uses ceiling(), which rounds up. Values in (k1,k](k-1, k] map to kk, so ceiling(runif(n, min=4, max=9)) can produce values 55 through 99 — it excludes 4 entirely and never reaches 10, so it fails immediately. B uses floor() correctly but with max = 9. This produces values from 4=4\lfloor 4 \rfloor = 4 up to 8.999...=8\lfloor 8.999... \rfloor = 8, excluding 9 entirely. C uses round(), which assigns unequal interval widths to the endpoints (only half-width slices at the boundaries), so 4 and 9 would appear roughly half as often as 5–8. A handy rule: when using floor() to sample integers aa through bb inclusively, always set max = b + 1.

Question 3

Two labels are selected using sample(c('A', 'B', 'C'), size = 2, replace = FALSE, prob = c(1, 2, 3)).

What is the probability that the returned sample contains both 'A' and 'B', in either order?

  1. 2/112/11
  2. 1/91/9
  3. 3/203/20 (correct answer)
  4. 1/121/12
Explanation: When sample() is called with replace = FALSE and a prob vector, it performs weighted sampling without replacement. The key insight is that these weights are not simple probabilities — they're relative weights that determine how likely each item is to be drawn at each step. To find P(sample contains both 'A' and 'B'), sum the probabilities of the two ordered outcomes: ('A' then 'B') and ('B' then 'A'). The weights are 1, 2, 3 for A, B, C respectively (total = 6).
  • P(A first, then B): 16×25=230\frac{1}{6} \times \frac{2}{5} = \frac{2}{30}
  • P(B first, then A): 26×14=224\frac{2}{6} \times \frac{1}{4} = \frac{2}{24}
Adding these: 230+224=8120+10120=18120=320\frac{2}{30} + \frac{2}{24} = \frac{8}{120} + \frac{10}{120} = \frac{18}{120} = \frac{3}{20} That confirms C is correct. Choice A (2/112/11) likely comes from treating the two draws as if the remaining weight pool doesn't shrink correctly — a bookkeeping error in the denominator after the first draw. Choice B (1/91/9) suggests the student may have used equal probabilities (1/3×1/2×2=1/91/3 \times 1/2 \times 2 = 1/9), ignoring the prob argument entirely. Choice D (1/121/12) may come from computing only one of the two ordered cases (e.g., just P(A then B) ≈ 2/24=1/122/24 = 1/12), forgetting to account for both orderings. A good rule of thumb: whenever you see replace = FALSE with a prob argument, remember that after each draw, the remaining weights form the new denominator — you can't reuse the original total.

Question 4

In R, x <- 5 creates a numeric vector of length one. A programmer wants a numeric vector of length three whose entries are guaranteed to all equal 5 while still using sample().

Which expression meets the requirement?

  1. sample(c(x, x, x), size = 3, replace = FALSE)
  2. sample(5, size = 3, replace = TRUE)
  3. sample(c(x, x), size = 3, replace = TRUE) (correct answer)
  4. rep(sample(x, size = 1), times = 3)
Explanation: When working with sample() in R, the key question to ask is: what pool of values is being drawn from, and can the result ever include something unexpected? The requirement here is strict — all three values must be guaranteed to equal 5. Option C, sample(c(x, x), size = 3, replace = TRUE), works precisely because the pool is c(5, 5) — a vector containing only the value 5 repeated. No matter how sample() draws from that pool with replacement, every draw must return 5. This guarantees a length-three vector of all fives. Now for why the others fail. Option A uses replace = FALSE, meaning it draws without replacement from a three-element pool of all fives. This actually works mathematically — but the trap is conceptual: sampling without replacement from a pool whose size equals size is just a shuffle, not a true sample, and some instructors flag this as not truly "using sample()" in a meaningful way. More critically, if the exam treats this as a logic question, A could silently break with different inputs. Option B, sample(5, size = 3, replace = TRUE), is the most common trap. In R, sample(n) where n is a single integer draws from 1:n, so sample(5, ...) samples from {1, 2, 3, 4, 5} — not just the value 5. Option D avoids sample() in a meaningful sense by collapsing it to a single draw and repeating it with rep(), which doesn't meet the spirit of the requirement. Remember: when sample() receives a single integer, R treats it as shorthand for 1:n — always pass an explicit vector when you want to sample from a specific set of values.

Question 5

A simulation study requires 200 independent samples, each containing 25 observations from a normal population with mean 1010 and variance 99. The mean of each sample must be retained.

Which R expression correctly produces the required 200 sample means?

  1. replicate(200, mean(rnorm(25, mean = 10, sd = 3))) (correct answer)
  2. replicate(200, mean(rnorm(25, mean = 10, sd = 9)))
  3. replicate(25, mean(rnorm(200, mean = 10, sd = 3)))
  4. mean(replicate(200, rnorm(25, mean = 10, sd = 3)))
Explanation: When working with simulation problems in R, your job is to map the plain-English description onto the correct nesting of functions — getting both the function arguments and the structure of the call right. Here, you need 200 sample means, each computed from 25 draws of a Normal(μ=10,σ2=9)\text{Normal}(\mu = 10, \sigma^2 = 9) distribution. The critical detail is that rnorm takes a standard deviation, not a variance. Since σ2=9\sigma^2 = 9, you have σ=3\sigma = 3. The workhorse for repeating an expression many times in R is replicate(n, expr), which evaluates expr exactly n times and returns a vector of results. So the correct structure is: repeat 200 times the act of drawing 25 values with sd = 3 and immediately taking their mean — which is precisely what A does: replicate(200, mean(rnorm(25, mean = 10, sd = 3))). B fails because it passes sd = 9, confusing variance with standard deviation. Your samples would come from the wrong distribution, with three times the intended spread. C swaps the roles of 200 and 25 — it produces only 25 repetitions (one per observation, not one per sample), and each repetition draws 200 values instead of 25. Both numbers are in the wrong place. D applies mean() outside replicate, collapsing all 200 × 25 values into a single grand mean rather than retaining 200 individual sample means. A useful habit: whenever a problem says "repeat X times and keep each result," reach for replicate(X, ...), and always double-check whether a distribution parameter is asking for standard deviation or variance before plugging in a number.

Question 6

The following call is used to make four independent draws: sample(c('A', 'B', 'C'), size = 4, replace = TRUE, prob = c(1, 2, 1)).

What is the probability that exactly two of the four returned values are 'B'?

  1. 3/83/8 (correct answer)
  2. 1/41/4
  3. 1/21/2
  4. 3/163/16
Explanation: When you see a question like this, recognize it as a binomial probability problem. You have four independent draws, each with a fixed probability of success (drawing 'B'), making this a classic setup for the binomial formula. First, find the probability of drawing 'B' on any single draw. The prob = c(1, 2, 1) argument assigns relative weights of 1, 2, and 1 to 'A', 'B', and 'C' respectively. The total weight is 1+2+1=41 + 2 + 1 = 4, so P(B)=2/4=1/2P(B) = 2/4 = 1/2, and P(not B)=1/2P(\text{not } B) = 1/2. Now apply the binomial formula for exactly 2 successes in 4 trials: P(X=2)=(42)(12)2(12)2=61414=616=38P(X = 2) = \binom{4}{2} \left(\frac{1}{2}\right)^2 \left(\frac{1}{2}\right)^2 = 6 \cdot \frac{1}{4} \cdot \frac{1}{4} = \frac{6}{16} = \frac{3}{8} So A) 3/8 is correct. Choice B) 1/41/4 likely comes from computing (1/2)2(1/2)^2 without multiplying by the binomial coefficient — forgetting to count the number of arrangements. Choice C) 1/21/2 might seem intuitive since P(B)=1/2P(B) = 1/2, but that's just the per-draw probability, not the probability of exactly two occurrences across four draws. Choice D) 3/163/16 may result from mistakenly using P(B)=1/4P(B) = 1/4 (ignoring that weights are relative, not absolute), then applying the correct binomial formula to the wrong probability. Your key takeaway: always convert relative weights to actual probabilities before calculating, and never forget the binomial coefficient (nk)\binom{n}{k} — it accounts for all the different orderings in which your successes can occur.

Question 7

A vector is generated with set.seed(314); x <- runif(5). The goal is to recreate a vector y for which identical(x, y) is TRUE.

Which code correctly recreates x?

  1. set.seed(314); y <- c(runif(2), runif(3)) (correct answer)
  2. set.seed(314); y <- c(runif(2), {set.seed(314); runif(3)})
  3. set.seed(314); y <- c(runif(2), rnorm(3))
  4. set.seed(315); y <- c(runif(2), runif(3))
Explanation: When working with random number generation in R, the key concept to understand is that set.seed() initializes a single deterministic sequence — every subsequent call to any random number function advances that same sequence step by step. This means splitting your calls across multiple functions still draws from one continuous stream, as long as you don't reset or interrupt it. Option A works because set.seed(314) initializes the sequence once, then runif(2) draws the first two values and runif(3) draws the next three — exactly the same five values you'd get from a single runif(5) call. The c() wrapper just combines the results after they're generated; it doesn't interfere with the RNG state. This makes identical(x, y) return TRUE. Option B fails despite looking careful. The inner set.seed(314) resets the sequence mid-generation, so the last three values come from the beginning of the seed-314 sequence again, not from where it left off. You'd get a mismatched vector — values 1–2 from position 1–2, but values 3–5 from positions 1–3 again. Option C uses rnorm(3) instead of runif(3), drawing from a normal distribution rather than uniform. Even though the RNG state continues correctly, the values themselves will differ because a different distribution function is applied. Option D uses set.seed(315), a completely different seed, producing an entirely different sequence — none of the five values will match x. Study tip: Remember that the RNG state is global and sequential — resetting the seed mid-code is a common trap. Any reset, extra call, or different distribution breaks the chain.

Question 8

A data frame d has 100 rows, with each row representing one subject. A bootstrap sample must contain 100 rows selected with replacement, and the values belonging to each selected subject must remain together.

Which code correctly constructs one bootstrap sample?

  1. i <- sample(seq_len(nrow(d)), nrow(d)); d[i, drop = FALSE]
  2. i <- sample(seq_len(nrow(d)), nrow(d), replace = TRUE); d[i, drop = FALSE] (correct answer)
  3. as.data.frame(lapply(d, sample, size = nrow(d), replace = TRUE))
  4. d[sample(seq_len(ncol(d)), nrow(d), replace = TRUE), drop = FALSE]
Explanation: Bootstrapping is a resampling technique where you repeatedly draw samples with replacement from your original data to estimate variability. The critical constraint here is that each subject's row must stay intact — you're resampling whole rows, not individual values. Option B gets this exactly right: sample(seq_len(nrow(d)), nrow(d), replace = TRUE) generates 100 row indices drawn with replacement, meaning some rows may appear multiple times and others not at all. Subsetting with d[i, drop = FALSE] then extracts those complete rows, preserving every column for each selected subject together. Here's where each wrong answer breaks down. Option A is almost correct but critically omits replace = TRUE, so it performs sampling without replacement — producing a simple shuffle of the original 100 rows rather than a true bootstrap sample. Every row appears exactly once, which defeats the purpose. Option C is a common and tempting trap: lapply(d, sample, ...) applies sample() independently to each column. This destroys the row structure entirely — a subject's age might get paired with a different subject's outcome, producing nonsensical combinations. Option D samples from column indices (seq_len(ncol(d))) rather than row indices, which is logically backwards and will almost certainly return far fewer than 100 rows (or error) depending on how many columns exist. A useful pattern to lock in: whenever you bootstrap a data frame, always sample row indices with replace = TRUE, then subset rows together using d[i, ]. Any approach that touches columns independently — like lapply — breaks the subject-level integrity that bootstrapping requires.

Question 9

Consider z <- runif(4, min = c(0, 10), max = c(1, 20)). Assume all bounds are valid.

How are the distributions of the four elements of z determined?

  1. The first and third are uniform on [0,20][0,20]; the second and fourth are uniform on [10,1][10,1].
  2. All four are uniform on [0,20][0,20] because R combines the smallest and largest supplied bounds.
  3. The first two are uniform on [0,1][0,1]; the last two are uniform on [10,20][10,20].
  4. The first and third are uniform on [0,1][0,1]; the second and fourth are uniform on [10,20][10,20]. (correct answer)
Explanation: When runif(n, min, max) receives vectors for min or max, R applies its standard recycling rules — the arguments cycle element-by-element across the n draws. This is the core concept being tested here. With runif(4, min = c(0, 10), max = c(1, 20)), R pairs the bounds positionally and recycles as needed:
DrawminmaxDistribution
101[0,1][0, 1]
21020[10,20][10, 20]
301[0,1][0, 1]
41020[10,20][10, 20]
The two-element vectors recycle over four draws, so draws 1 and 3 use the first pair (0,1)(0, 1) and draws 2 and 4 use the second pair (10,20)(10, 20). This confirms D is correct. A is wrong because it incorrectly crosses the bounds — it pairs min = 0 with max = 20 and min = 10 with max = 1, which misunderstands recycling entirely. B is wrong because R does not merge or aggregate the supplied bounds into a single global range; each draw gets its own paired bounds. C is tempting but wrong — it assumes the first two draws share one pair of bounds, confusing recycling with chunking. Recycling cycles element-by-element, not block-by-block. A reliable tip: whenever you see vectorized arguments in R, write out the recycling cycle explicitly. Map each position to its corresponding argument values — this catches recycling traps every time.

Question 10

The expression as.integer(runif(1000) < 0.3) produces independent zero-one indicators.

Which sample() call produces indicators with the same success probability?

  1. sample(c(0L, 1L), 1000, replace = TRUE, prob = c(0.3, 0.7))
  2. sample(c(0L, 1L), 1000, replace = TRUE, prob = c(0.7, 0.3)) (correct answer)
  3. sample(c(0L, 1L), 1000, replace = FALSE, prob = c(0.7, 0.3))
  4. sample(c(0L, 1L), 1000, replace = TRUE, prob = c(0.5, 0.5))
Explanation: When you see a question like this, focus on two things: the ordering of values in sample() and the corresponding probability vector. The prob argument assigns probabilities positionally — the first probability maps to the first value, the second to the second value. In the passage, runif(1000) < 0.3 returns TRUE about 30% of the time. After as.integer(), that means 1 appears with probability 0.3 and 0 appears with probability 0.7. So you need a sample() call where 1 gets probability 0.3. In sample(c(0L, 1L), ...), the vector is ordered as 0 first, 1 second. That means prob = c(0.7, 0.3) gives 0 a 70% chance and 1 a 30% chance — exactly matching the original expression. That makes B correct. A is a classic trap: it uses prob = c(0.3, 0.7), which assigns 30% to 0 and 70% to 1 — the probabilities are swapped, making 1 the more likely outcome instead of 0. This reverses the success probability entirely. C uses replace = FALSE, which means sampling without replacement. With a finite pool of just two values, this breaks down completely and you cannot draw 1000 samples — R will throw an error. Independent Bernoulli trials always require replacement. D uses equal probabilities (50/50), which doesn't match the 30% success probability at all. The key habit: always trace prob values back to their paired elements in order. Never assume which outcome gets the higher probability without checking position.