Data Preprocessing Quick Reference
Everything you need day‑to‑day – cleaning, scaling, encoding, and feature engineering.
Data Cleaning
Handling Missing Values
Check for Missing
df.isnull().sum()
df.isnull().sum().sum()
df.info() # shows non‑null counts
Remove Missing
df.dropna() # drop rows with any NaN df.dropna(thresh=3) # rows with ≥3 non‑null df.dropna(subset=['col1']) # specific columns
Imputation
# Simple df.fillna(0) df.fillna('missing') df['col'].fillna(df['col'].mean()) df['col'].fillna(df['col'].median()) df['col'].fillna(df['col'].mode()[0]) # Forward/Backward df.fillna(method='ffill') df.fillna(method='bfill')
Advanced Imputation
from sklearn.impute import SimpleImputer, KNNImputer # SimpleImputer imputer = SimpleImputer(strategy='mean') df_imputed = imputer.fit_transform(df) # KNN Imputer imputer = KNNImputer(n_neighbors=5) df_imputed = imputer.fit_transform(df) # Iterative Imputer from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer imputer = IterativeImputer() df_imputed = imputer.fit_transform(df)
Handling Outliers
Detection
# Z‑score from scipy import stats z_scores = np.abs(stats.zscore(df)) outliers = (z_scores > 3).all(axis=1) # IQR Q1 = df.quantile(0.25) Q3 = df.quantile(0.75) IQR = Q3 - Q1 outliers = ((df < (Q1 - 1.5 * IQR)) | (df > (Q3 + 1.5 * IQR))).any(axis=1) # Isolation Forest from sklearn.ensemble import IsolationForest iso = IsolationForest(contamination=0.1) outliers = iso.fit_predict(df) == -1
Treatment
# Remove df_clean = df[~outliers] # Cap/Winsorize def cap_outliers(df, col, lower, upper): df[col] = df[col].clip(lower=lower, upper=upper) # Transform df['col_log'] = np.log(df['col']) df['col_sqrt'] = np.sqrt(df['col']) df['col_inv'] = 1 / df['col']
Removing Duplicates
df.drop_duplicates() # drop all duplicates df.drop_duplicates(subset=['col1', 'col2']) # based on specific columns df.drop_duplicates(keep='last') # keep last occurrence
Feature Scaling
Standardization (Z‑Score)
- Mean = 0, Std = 1
- Formula: (x - μ) / σ
- Use when features have different units
- Works for most algorithms (SVM, Logistic Regression, Neural Nets)
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() df_scaled = scaler.fit_transform(df)
Min‑Max Scaling (Normalization)
- Range: [0, 1]
- Formula: (x - min) / (max - min)
- Use when data has bounded range
- Sensitive to outliers
- Good for neural networks, K‑NN
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df_scaled = scaler.fit_transform(df)
// Custom range
scaler = MinMaxScaler(feature_range=(-1, 1))
Robust Scaling
- Uses median and IQR
- Formula: (x - median) / IQR
- Robust to outliers
- Use when outliers are present
from sklearn.preprocessing import RobustScaler scaler = RobustScaler() df_scaled = scaler.fit_transform(df)
Normalizer (L2/L1 Norm)
- Scales rows (samples) to unit norm
- L2: Euclidean norm = 1
- L1: Manhattan norm = 1
- Use for text data, embeddings, distance‑based
from sklearn.preprocessing import Normalizer
scaler = Normalizer(norm='l2') // 'l1', 'l2', 'max'
df_scaled = scaler.fit_transform(df)
Scaling Comparison
| Method | Formula | Range | Outlier Robust | Use Case |
|---|---|---|---|---|
| StandardScaler | (x - μ) / σ | μ=0, σ=1 | No | General, many algorithms |
| MinMaxScaler | (x - min) / (max - min) | [0,1] | No | Neural nets, bounded data |
| RobustScaler | (x - median) / IQR | Variable | Yes | Data with outliers |
| Normalizer | x / ||x|| | Unit norm | No | Row‑wise, text, embeddings |
| MaxAbsScaler | x / max(|x|) | [-1,1] | No | Sparse data, images |
Encoding Categorical Variables
Label Encoding
- Maps categories to integers (0, 1, 2, ...)
- Use for ordinal data (order matters)
- May imply ordinal relationship
from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df['col_encoded'] = le.fit_transform(df['col'])
One‑Hot Encoding
- Creates binary columns for each category
- Use for nominal data (no order)
- Avoids ordinal assumption
- Can create many columns (curse of dimensionality)
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse_output=False)
encoded = encoder.fit_transform(df[['col']])
// With pandas
df_encoded = pd.get_dummies(df, columns=['col1', 'col2'])
Ordinal Encoding
- Maps categories to ordered integers
- Define mapping explicitly
- Use when order is known
from sklearn.preprocessing import OrdinalEncoder
encoder = OrdinalEncoder(categories=[['low', 'medium', 'high']])
df_encoded = encoder.fit_transform(df[['col']])
// Custom mapping
mapping = {'low': 0, 'medium': 1, 'high': 2}
df['col_encoded'] = df['col'].map(mapping)
Target Encoding
- Replace categories with target mean
- Use for high cardinality
- Risk of overfitting (use smoothing)
// Mean encoding df['col_target'] = df.groupby('col')['target'].transform('mean') // With smoothing global_mean = df['target'].mean() k = 5 df['col_encoded'] = (df.groupby('col')['target'].transform('sum') + global_mean * k) / (df.groupby('col')['target'].transform('count') + k)
Frequency Encoding
- Replace with category frequency
- Use for high cardinality
- Simple and effective
df['col_freq'] = df['col'].map(df['col'].value_counts() / len(df))
Binary Encoding
- Convert to binary, then one‑hot
- Less columns than one‑hot
- Use when many categories
!pip install category_encoders import category_encoders as ce encoder = ce.BinaryEncoder() df_encoded = encoder.fit_transform(df['col'])
Encoding Comparison
| Method | Use Case | Output | Maintains Order | Cardinality |
|---|---|---|---|---|
| Label Encoding | Ordinal | 1 column | Yes | Any |
| One‑Hot Encoding | Nominal | N columns | No | Low (< 20) |
| Ordinal Encoding | Ordered | 1 column | Yes | Any |
| Target Encoding | High cardinality | 1 column | No | High |
| Frequency Encoding | High cardinality | 1 column | No | High |
| Binary Encoding | Medium cardinality | log₂(N) | No | Medium |
Feature Engineering
Polynomial Features
- Adds polynomial combinations
- Captures non‑linear relationships
- Risk of overfitting
from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2, include_bias=False) df_poly = poly.fit_transform(df)
Interaction Terms
- Product of two features
- Captures interactions
- Use with caution (increases dimensionality)
df['interact'] = df['col1'] * df['col2'] df['interact'] = df['col1'] / df['col2']
Binning
- Convert continuous to categorical
- Use equal‑width or equal‑frequency
- Can lose information
df['binned'] = pd.cut(df['col'], bins=5) df['binned'] = pd.qcut(df['col'], q=5, labels=False)
Log / Transform
- Log transform for skewed data
- Square root, Box‑Cox, Yeo‑Johnson
df['log'] = np.log1p(df['col']) // log(1+x)
df['sqrt'] = np.sqrt(df['col'])
df['boxcox'], _ = stats.boxcox(df['col'] + 1)
Date/Time Features
- Extract year, month, day, hour, etc.
- Day of week, quarter, week number
- Cyclical encoding (sin/cos)
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['weekday'] = df['date'].dt.dayofweek
df['hour'] = df['date'].dt.hour
// Cyclical
df['month_sin'] = np.sin(2 * np.pi * df['month'] / 12)
df['month_cos'] = np.cos(2 * np.pi * df['month'] / 12)
Text Features
- Length, word count
- TF‑IDF, Bag‑of‑Words
- Sentiment, entities, keywords
df['len'] = df['text'].str.len()
df['word_count'] = df['text'].str.split().str.len()
// TF‑IDF
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(max_features=100)
X_tfidf = tfidf.fit_transform(df['text'])
Data Splitting
Train‑Test Split
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
// Stratified (for classification)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
Train‑Validation‑Test Split
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.3, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
// Or with validation_split in some libraries
Cross‑Validation
from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold // k‑fold CV kf = KFold(n_splits=5, shuffle=True, random_state=42) scores = cross_val_score(model, X, y, cv=kf) // Stratified k‑fold skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) // Time Series split from sklearn.model_selection import TimeSeriesSplit tscv = TimeSeriesSplit(n_splits=5)
Pipeline
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
// Preprocessing pipeline
preprocessor = ColumnTransformer([
('num', StandardScaler(), numeric_cols),
('cat', OneHotEncoder(), categorical_cols)
])
pipeline = Pipeline([
('preprocessor', preprocessor),
('classifier', LogisticRegression())
])
pipeline.fit(X_train, y_train)
pipeline.score(X_test, y_test)
Best Practices
- Fit on train only – Always fit scalers/encoders on training data, then transform test.
- Avoid data leakage – Don't use information from test set.
- Handle missing before scaling – Impute first, then scale.
- Feature selection – Remove irrelevant features.
- Domain knowledge – Use to create meaningful features.
- Iterate – Feature engineering is iterative.
- Validate – Always validate with cross‑validation.
- Document – Document your preprocessing steps.
- Automate – Use pipelines for reproducibility.
- Version – Track preprocessing with version control.
📌 Quick Reference
Missing data: dropna(), fillna(), SimpleImputer, KNNImputer
Scaling: StandardScaler (μ=0, σ=1), MinMaxScaler ([0,1]), RobustScaler (median/IQR), Normalizer
Encoding: Label (ordinal), One‑Hot (nominal), Target (high cardinality), Frequency (high cardinality)
Split: train_test_split, cross_val_score, stratified (classification)
Pipeline: Combine preprocessing + model
Always: Fit on train only, avoid leakage, use pipelines
Scaling: StandardScaler (μ=0, σ=1), MinMaxScaler ([0,1]), RobustScaler (median/IQR), Normalizer
Encoding: Label (ordinal), One‑Hot (nominal), Target (high cardinality), Frequency (high cardinality)
Split: train_test_split, cross_val_score, stratified (classification)
Pipeline: Combine preprocessing + model
Always: Fit on train only, avoid leakage, use pipelines