Random Sampling
Select observations from a finite collection with or without replacement. Connect replacement to repeated selections, validate non-uniform probabilities, and choose a sample size that is possible under the stated rule.
Sampling selects some observations from a defined collection. The collection available for selection is the population, and the selected observations form the sample.
For example, a program may select four record identifiers from eight available identifiers:
Before interpreting the result, state the population, requested sample size, replacement rule, and selection probabilities. These choices define what samples are possible.
Sample with replacement
By default, rng.choice samples with replacement:
sample = rng.choice(record_ids, size=4, replace=True)
After each draw, the selected population item remains available for another draw. The same identifier can therefore appear more than once:
[104, 101, 104, 107]
This is not an error. The two occurrences of 104 represent two selections of
the same population item.
With replacement, the requested sample may be larger than the population:
Only two outcomes are available, but either can be selected repeatedly.
Sample without replacement
Set replace=False when one population position may be selected at most once:
sample = rng.choice(record_ids, size=4, replace=False)
The selected identifiers are distinct because every value in record_ids is
distinct. The requested sample size cannot exceed the population size:
rng.choice(record_ids, size=9, replace=False)
This call cannot select nine different positions from a population of eight, so NumPy raises an error.
Without replacement prevents repeated positions, not necessarily repeated values. Consider:
scores = np.array([8, 8, 9, 10])
Two different population positions contain the value 8. A sample without
replacement can contain both values because the selected positions are
different.
Use indexes when identity matters
Sampling values can hide which population positions were selected. When rows have an identity or several arrays must remain aligned, sample indexes:
One shared index array preserves each name–score pair. The next lesson applies the same principle when shuffling and splitting entire datasets.
Assign non-uniform probabilities
Without a p argument, each population position is equally likely at a draw.
Pass one probability per population position when the selection rule is
different:
The probability array must satisfy three basic conditions:
probability.shape == (population size,)
every probability >= 0
probability.sum() == 1, within floating-point tolerance
Each probability belongs to the population item at the same position:
| Position | Label | Probability |
|---|---|---|
| 0 | common | 0.70 |
| 1 | uncommon | 0.25 |
| 2 | rare | 0.05 |
If the labels are reordered without reordering the probabilities, the program implements a different sampling rule even though both arrays still have valid shapes.
Use np.isclose for a floating-point sum check:
Inspect one sample without overinterpreting it
Run the demonstration and change the seed or number of draws.
Compare equal and weighted sampling
The printed counts describe two finite samples. Increase draw_count to see how the observed proportions behave over more draws.
Ready to run.
A probability of 0.70 does not guarantee exactly 21 occurrences in a
sample of 30. It defines the probability at each draw. Finite sample counts
vary. A larger number of draws often produces proportions closer to the
specified probabilities, but any one sample still contains random variation.
Keep the output shape explicit
As with other generator methods, size determines the output shape:
batch_sample = rng.choice(record_ids, size=(2, 3), replace=True)
The result has shape (2, 3) and contains six selections. For sampling
without replacement, those six selected population positions must be distinct
across the complete output.
Before using a sample, useful checks include:
The unique-value count must be interpreted with the population. It proves that the sampled values are distinct only when population values are themselves distinct.
State what the sample can represent
Random selection removes one source of deliberate choice, but it does not automatically make a sample representative of a wider real-world population. The available population may already omit important groups, contain duplicates, or reflect a biased collection process.
Distinguish these questions:
- Was the sampling code consistent with its stated rule?
- Was the available population appropriate for the question?
- Is the sample large and structured enough for the conclusion being drawn?
This lesson answers the first question. Later work in probability, statistics, and model evaluation develops the other two.
Exercise: Choose sampling without replacement
Which argument prevents one population position from being selected twice in the same sample?
Answer it first, then check.
HintControl whether an item returns
Use the replace argument.
SolutionSet replace=False
With replace=False, a selected population position is not available for
another selection in that sample.
Exercise: Check whether a sample size is possible
A population contains five records. Which request is valid?
Select one choice, then check.
HintCompare sample and population sizes
A sample larger than the population requires repeated selections.
SolutionUse replacement for eight draws
With replacement, each of the eight draws can select any of the five records. Without replacement, at most five positions can be selected.
Exercise: Interpret duplicate values
The population is np.array([8, 8, 9, 10]). A sample drawn with
replace=False contains [8, 8]. What does this show?
Select one choice, then check.
HintTrack indexes, not only values
The two occurrences of 8 can belong to different indexes.
SolutionDistinct positions can contain equal values
Sampling without replacement prevents repeated positions. It does not make duplicate values in the original population unique.
Exercise: Validate weighted sampling
Which probability array is valid for a three-item population?
Select one choice, then check.
HintCheck three conditions
The array needs three entries, no negative values, and a sum of 1.0.
SolutionUse [0.50, 0.30, 0.20]
This array has one probability for each item, every value is non-negative,
and the probabilities sum to 1.0.
Exercise: Sample aligned records by index
Complete the program so it selects three distinct indexes and uses them for both arrays. The output must report:
sample size: 3
indexes distinct: True
pairs valid: True
Preserve record pairs while sampling
Ready to run.
HintSample positions once
Use rng.choice(len(names), size=3, replace=False), then index both arrays
with the result.
SolutionUse one sample of shared indexes
Sampling indexes preserves record identity. Applying the same three indexes to both arrays keeps every selected name aligned with its score.
Retain the sampling contract
Describe every sample with:
population
+ sample size and shape
+ replacement rule
+ selection probabilities
+ recorded generator state or seed
= sampling contract
Then verify that the code follows the contract. Only after that check should you ask whether the available population and resulting sample support the larger conclusion.