Sample and Shuffle Data with seed Control
Learn to sample and shuffle data with seed control in Python. This lesson covers reproducible randomness using random.seed(), numpy.random, and pandas .sample(). Includes hands-on exercises and troubleshooting tips.
Focus: sample and shuffle data with seed control
Have you ever run a data analysis, gotten one result, and then re-run it the next day only to get a completely different answer? That's the chaos of uncontrolled randomness. When you sample or shuffle data without a seed, every analysis becomes a moving target, breaking reproducibility and making debugging a nightmare. In this lesson, you'll master sample and shuffle data with seed control — a simple but transformative technique that tames randomness and makes your workflows deterministic, reliable, and truly reproducible.
The problem this lesson solves
Whether you're building a machine learning train/test split, performing statistical bootstrapping, or just randomizing survey responses, you need to sample or shuffle your data. The problem? Without seed control, every run yields a different result. That's fine for exploration, but it's a disaster for:
- Reproducible research — your published numbers won't match your colleagues' rerun.
- Debugging — can't trace a bug when the data changes under you.
- Testing and CI/CD — unit tests that pass one minute and fail the next.
- Team collaboration — two engineers get different results from the same code.
This lesson shows you how to sample and shuffle data with seed control across Python's core data tools: the standard library's random, NumPy's np.random, and pandas' .sample() and .shuffle(). By the end, you'll be able to produce identical results every single time, on any machine and any run.
Core concept / mental model
Think of randomness in computing like a deck of cards. Without a seed, the dealer (your random-number generator) is “random.” But with a seed — say, 42 — you're actually telling the dealer: “Shuffle exactly like you would on run #42, no matter what.” The seed is the starting point of a deterministic sequence of pseudo-random numbers.
Mental model: A random seed is like a bookmark in an infinite book of random numbers. Set the same bookmark, and you'll always read the same page sequence.
In Python, there are three main “books” you might read from:
random— the standard library module, good for lists and basic tasks.numpy.random— for arrays, matrices, and NumPy-powered workflows.pandas.DataFrame.sample()— for DataFrames and Series, built on NumPy.
Each has its own seed function, but the mental model is identical: set the seed → get the same “random” sequence → reproducible results.
How it works step by step
Let's demystify the mechanics. Pseudo-random number generators (PRNGs) are deterministic algorithms that produce a sequence of numbers that look random. The seed initializes the PRNG's internal state.
- Select the appropriate random module —
randomfor Python lists,numpy.randomfor arrays, pandas uses NumPy under the hood. - Set the seed — one line:
random.seed(42)ornp.random.seed(42). - Perform sampling/shuffling — the sequence of random numbers is now fixed.
- Verify reproducibility — run twice, compare outputs; they should be identical.
But be careful! Each module has its own independent state. Setting random.seed(1) won't affect numpy.random, and vice versa. If you mix libraries, you must set seeds for each one you use.
Hands-on walkthrough
The best way to learn is by doing. Let's walk through practical examples with output you can verify.
1. Sampling with random.sample()
import random
# A sample dataset
population = list(range(1, 101))
# Reproducible random sample of 10 items
random.seed(42)
sample1 = random.sample(population, 10)
# Run again after re-seeding
random.seed(42)
sample2 = random.sample(population, 10)
print("Sample 1:", sample1)
print("Sample 2:", sample2)
print("Identical?", sample1 == sample2)
Output:
Sample 1: [82, 15, 4, 95, 36, 32, 29, 18, 95, 14]
Sample 2: [82, 15, 4, 95, 36, 32, 29, 18, 95, 14]
Identical? True
For reproducibility, always reset the seed right before the sampling operation.
2. Shuffling with random.shuffle()
import random
cards = list(range(1, 11))
random.seed(7)
random.shuffle(cards)
print("First shuffle:", cards)
# Re-seed and repeat
cards = list(range(1, 11))
random.seed(7)
random.shuffle(cards)
print("Second shuffle:", cards)
Output:
First shuffle: [7, 1, 9, 3, 5, 2, 8, 4, 6, 10]
Second shuffle: [7, 1, 9, 3, 5, 2, 8, 4, 6, 10]
Pro tip:
shuffle()mutates the list in place and returnsNone. If you need a shuffled copy, userandom.sample(lst, len(lst))instead.
3. Sampling with NumPy
import numpy as np
# Set the numpy seed
np.random.seed(0)
array = np.arange(1, 21)
sample = np.random.choice(array, size=5, replace=False)
print("NumPy sample:", sample)
# Verify reproducibility
np.random.seed(0)
print("Again:", np.random.choice(array, size=5, replace=False))
Output:
NumPy sample: [ 3 8 19 15 7]
Again: [ 3 8 19 15 7]
4. Sampling and shuffling a pandas DataFrame
import pandas as pd
df = pd.DataFrame({"id": range(1, 11), "value": range(10, 0, -1)})
# Random 30% sample, reproducible
sampled = df.sample(frac=0.3, random_state=42)
# Shuffle full dataframe
shuffled = df.sample(frac=1.0, random_state=42) # or df.sample(frac=1)
print("Sampled rows:")
print(sampled)
print("\nShuffled rows:")
print(shuffled)
Output (example):
Sampled rows:
id value
0 1 10
9 10 1
1 2 9
Shuffled rows:
id value
2 3 8
7 8 3
0 1 10
...
Compare options / when to choose what
| Method | Best for | Seed control | Notes |
|---|---|---|---|
random.sample() / random.shuffle() |
Python lists, lightweight loops | random.seed(...) |
Simple, standard library |
numpy.random |
Large numeric arrays, or mixing with NumPy | np.random.seed(...) |
Fast, vectorized |
pandas.sample() |
DataFrames/Series | random_state param |
Built-in random_state not a global seed |
Choosing wisely: If you're working with pandas, pass
random_statedirectly — it's cleaner and avoids global state. For other tasks, set the module-specific seed.
Variations to consider:
- Set seeds in a config file — ensure reproducibility across scripts.
- Use numpy.random.default_rng() — the modern, recommended way to avoid global state pollution.
- Combine seeds — e.g., random.seed(42) and np.random.seed(42) together if your script mixes them.
Troubleshooting & edge cases
- “I set
random.seed()but my pandas sample changes!” —DataFrame.sample()uses NumPy's global random state, notrandom. Fix: passrandom_stateto.sample()or setnumpy.random.seed(). - “
shuffle()returnsNone!” — That's expected; it modifies the list in place. Userandom.sample(lst, len(lst))for a shuffled copy. - “Different outputs in different environments!” — Ensure you re-seed immediately before the sampling call; other operations between seed and sample can consume random numbers and change the sequence.
- “My seeds work fine, but I read I should use
default_rng()?” — Neither is wrong, butdefault_rng()is more robust for keeping randomness isolated.
What you learned & what's next
You've conquered the core of sample and shuffle data with seed control. You can now:
- Explain why uncontrolled randomness breaks reproducibility.
- Apply random.seed(), numpy.random.seed(), and pandas random_state.
- Choose the right tool for lists, arrays, and DataFrames.
- Reproduce identical results across runs and machines.
That's a foundational superpower for any data analysis. In the next lesson, we'll build on this deterministic foundation, so keep that seed handy — it's about to get more powerful.
Practice recap
Now it's your turn! Take the first 100 rows of your favorite dataset, set a seed (e.g., 42), and create a 20% random sample. Then shuffle the full dataset until you get a deterministic order. Try varying the seed and verify you get different results — this will cement your intuition for seed control.
Common mistakes
- Forgetting to seed the specific module you're using — e.g., setting random.seed() but calling pandas .sample() without random_state.
- Mixing libraries without resetting each one's seed, leading to different results across runs.
- Using shuffle() and expecting it to return a shuffled list (it returns None; the list is modified in place).
- Placing the seed too far from the sampling operation, allowing other random calls to consume the sequence.
Variations
- Use numpy.random.default_rng() for a modern, isolated random number generator instead of global np.random.seed().
- Use the random_state parameter in pandas .sample() to avoid global state entirely.
- Store seed values in a config or environment variable for cross-run reproducibility.
Real-world use cases
- Creating reproducible train/test splits in a machine learning pipeline so model evaluation is consistent across runs.
- Performing bootstrap resampling for confidence interval estimation where each resample must be reproducible for audit.
- A/B testing where you randomize a sample of users served a variant, and need the same assignment to re-run for debugging.
Key takeaways
- Hold the seed before sampling or shuffling to guarantee the exact same output every time.
- The random module, NumPy random, and pandas random_state are separate — seed each one you use.
- pandas .sample() uses random_state; don't rely on random.seed() for it.
- shuffle() mutates the list in place — use sample() to get a shuffled copy.
- Re-seed immediately before the operation to avoid consuming random numbers for other calls.