Stratified splitting of pandas dataframe into training, validation and test set
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Stratified splitting divides a dataset into training, validation, and test sets while preserving the class distribution from the original data. This is critical for classification tasks — especially with imbalanced classes — because random splitting can produce splits where minority classes are underrepresented or entirely absent. Scikit-learn's train_test_split with the stratify parameter handles this.
Why Stratified Splitting?
Consider a dataset with 95% class A and 5% class B. A random split might give a test set with 0% class B, making it impossible to evaluate the model on the minority class. Stratified splitting guarantees each split has approximately the same class proportions as the original.
Two-Step Split: Train / Validation / Test
Scikit-learn's train_test_split only splits into two sets. To get three sets, split twice:
Verify the class distribution is preserved:
Working Directly with DataFrames
If you prefer to keep the DataFrame intact rather than separating X and y:
Custom Split Ratios
For a 70/15/15 split:
For an 80/10/10 split:
Multi-Class Stratified Splitting
Stratification works the same for multi-class problems:
Alternative: StratifiedShuffleSplit
For repeated stratified splits (useful in cross-validation):
Stratified K-Fold for Cross-Validation
When you do not want a fixed split and prefer cross-validation:
Common Pitfalls
- Too few samples per class: Stratification fails if a class has fewer samples than the number of splits. With very rare classes, consider merging categories or using
StratifiedShuffleSplitwhich is more forgiving. - Data leakage: Split before any preprocessing (normalization, feature engineering). Fitting a scaler on the full dataset before splitting leaks test set statistics into training.
- Forgetting
random_state: Without a fixedrandom_state, each run produces different splits, making experiments irreproducible. Always set it for reproducibility. - Ignoring group structure: If multiple rows belong to the same entity (e.g., multiple visits from one patient), use
GroupShuffleSplitorStratifiedGroupKFoldto keep all rows from one group in the same split. - Continuous targets:
stratifyonly works with categorical labels. For regression, use binning (pd.cut()) to create strata, or usetrain_test_splitwithout stratification.
Summary
- Use
train_test_splitwithstratify=yto preserve class distribution across splits - Split twice for train/val/test: first 60/40, then split the 40% into 50/50
- Always verify class proportions in each split with
value_counts(normalize=True) - Use
StratifiedKFoldfor cross-validation with stratification - Set
random_statefor reproducibility and split before any preprocessing
Related reading
- StratifiedKFold vs KFold in scikit-learn
- Streaming large training and test files into Tensorflow's DNNClassifier
- String Distance Matrix in Python
- String Matching Using Recurrent Neural Networks
- String analysis
- Subtract mean from image
- String Matching Using Recurrent Neural Networks
- Structuring dataset for OpenAI's GPT-3 fine tuning
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.