Feature Engineering
Intro
Good features beat clever models. Encode categoricals by cardinality,
impute missing data with mechanism in mind, scale only when the model
needs it, and wrap everything in a sklearn Pipeline so you cannot leak
the test set.
Overview
Encoding categoricals
- One-hot for nominal categories with < 15 unique values; use
drop_first=True to avoid multicollinearity.
- Ordinal for natural order (low/medium/high). Map explicitly —
never rely on alphabetical sort.
- Target encoding for high-cardinality nominals (city, zip).
Replace with mean target value, always with cross-validated
encoding to prevent leakage.
- Frequency encoding when category count or proportion is itself
predictive (popular products).
- Never label-encode nominals — it implies false ordinal
relationships.
Handling missing data
Understand the mechanism first: MCAR, MAR, or MNAR. Numerical
imputation: median (robust to outliers) or mean (preserves
distribution mean), with a binary _is_missing indicator if
missingness may be informative. Categorical imputation: mode for
low-cardinality, or treat missing as its own "unknown" category.
Advanced: KNN or iterative (MICE) imputation when features are
correlated. Drop rows only when < 5% are affected and missingness is
MCAR. Always fit imputers on training data only.
Feature scaling
- StandardScaler (z-score) — linear regression, SVM, PCA
- MinMaxScaler (0–1) — neural networks, bounded range
requirements; sensitive to outliers
- RobustScaler (IQR-based) — when outliers are present
- No scaling needed for tree-based models (Random Forest,
XGBoost)
Always fit on training data only and apply the same transform to
test data.
Feature selection
Filter methods (correlation, mutual information, chi-square) are
fast but ignore interactions. Wrapper methods (RFE, forward/backward)
consider combinations but are expensive. Embedded methods (Lasso,
tree importance, permutation importance) are the best
speed/accuracy balance. Remove zero-variance features first. Drop
one of each highly correlated pair (r > 0.9). Use domain knowledge
as the first filter before data-driven methods.
Time-series features
- Lag features —
value_lag_1, value_lag_7, value_lag_30
chosen by domain seasonality
- Rolling statistics —
value_rolling_mean_7d, std, min, max
over windows matching the pattern
- Seasonal features —
hour_of_day, day_of_week, month,
is_weekend, is_holiday; encode cyclical features as
sin(2*pi*hour/24) and matching cosine
- Difference features — period-over-period change, percent change
- Expanding statistics — cumulative mean, sum, count
Respect temporal ordering — never use future values as features.
Avoiding data leakage
Never compute features using information from the test set. Fit all
transformers (scaler, imputer, encoder) on training data only. For
time series, features must use only data available at prediction
time. Target encoding must use cross-validation folds, never the
full training set. Wrap preprocessing in sklearn.pipeline.Pipeline
to enforce ordering.
Gotchas
Agent-specific failure modes — provider-neutral pause-and-self-check items:
- Fitting transformers on the full dataset before splitting. Fitting a scaler, imputer, or target encoder on train + test leaks test-set statistics into the model. Fit all transformers on training data only, then transform test data with the training-fitted transformer.
- Target encoding without cross-validation. Replacing a categorical with its mean target value on the same fold creates direct leakage: the model learns to associate the target with... the target. Use cross-validated target encoding where each fold is encoded using only the other folds' statistics.
- Label-encoding nominal categories. Label encoding implies an ordinal relationship (e.g.,
Red=0, Blue=1, Green=2 implies Green > Blue > Red). Linear models and neural networks will learn a false ordering. Use one-hot or target encoding for nominals with no natural order.
- Time-series features that peek at future data. A lag-3 feature computed from row
t includes data from rows t+1, t+2, t+3 if the DataFrame is sorted descending. Verify temporal direction and always use only data available at prediction time.
- Applying MinMaxScaler when the test set contains values outside the training range. MinMaxScaler clips values to
[0, 1] based on training min/max. Out-of-range test values produce values outside [0, 1] or are clipped, corrupting the distribution. Use RobustScaler or StandardScaler for data with outliers or uncertain ranges.
- Polynomial feature expansion on all features "to be safe". Degree-2 expansion on 100 features produces ~5,000 features. Most of these will be noise, increasing training time and overfitting risk dramatically. Use polynomial features only for specific known non-linear relationships.
- Feature selection before splitting. Running mutual information or correlation-based selection on the full dataset lets test-set information guide which features are retained. Select features using only training data, ideally inside a sklearn Pipeline.
Full reference
Text features
- TF-IDF — baseline text representation; use
max_features to
cap dimensionality. Strong with traditional ML classifiers.
- Count vectorizer — simpler than TF-IDF when raw frequency is
enough.
- Embeddings — pre-trained sentence-transformers for semantic
similarity; superior for nuance, more expensive.
- Extracted features — text length, word count, punctuation
count, sentiment score, readability. Often more interpretable
than bag-of-words.
Combine TF-IDF + extracted features for a strong baseline before
reaching for embeddings.
Interaction and derived features
- Interaction terms for known relationships (
price * quantity = revenue)
- Ratio features (
clicks / impressions, revenue / users)
- Polynomial features sparingly (degree 2 max), only for known
non-linear relationships
- Binning continuous → categorical when the relationship is
step-wise (age groups, income brackets); use domain-driven bins,
not arbitrary quantiles
- Log transform right-skewed features (income, prices, counts)
Worked examples
- user_id, city, purchase_amount, timestamp: Cross-validated
target encoding on city; extract day_of_week, hour, is_weekend
from timestamp; lag features per user; rolling 7- and 30-day
purchase means; days_since_last_purchase. Wrap in a sklearn
Pipeline.
- 200 features, poor performance: Drop zero-variance and
near-constant columns, drop one of each correlated pair (r > 0.9),
rank with permutation importance on the baseline, retrain on top
30–50, compare. Audit remaining features for leakage.
- 40% missing income: Investigate MAR via correlation with
other features. Add
income_is_missing indicator. Impute median
from the training set (robust to skew). Compare model performance
to KNN imputation as an alternative.
Anti-patterns
- Fitting a scaler or encoder on the full dataset before splitting
- Target encoding without cross-validation (silent leakage)
- Label-encoding nominal categories
- Imputing nulls with column mean computed across train + test
- Time-series features that peek at future timestamps
- Polynomial expansion of every feature "to be safe"
1---2name: feature-engineering3description: Feature engineering for ML — encoding, imputation, scaling, selection, time-series features. Use when preparing data for an ML model, encoding categoricals, handling missing data, building time-series features, or selecting features from a wide table.4---56# Feature Engineering78## Intro910Good features beat clever models. Encode categoricals by cardinality,11impute missing data with mechanism in mind, scale only when the model12needs it, and wrap everything in a sklearn Pipeline so you cannot leak13the test set.1415## Overview1617### Encoding categoricals1819- **One-hot** for nominal categories with < 15 unique values; use20 `drop_first=True` to avoid multicollinearity.21- **Ordinal** for natural order (low/medium/high). Map explicitly —22 never rely on alphabetical sort.23- **Target encoding** for high-cardinality nominals (city, zip).24 Replace with mean target value, always with cross-validated25 encoding to prevent leakage.26- **Frequency encoding** when category count or proportion is itself27 predictive (popular products).28- **Never label-encode nominals** — it implies false ordinal29 relationships.3031### Handling missing data3233Understand the mechanism first: MCAR, MAR, or MNAR. Numerical34imputation: median (robust to outliers) or mean (preserves35distribution mean), with a binary `_is_missing` indicator if36missingness may be informative. Categorical imputation: mode for37low-cardinality, or treat missing as its own `"unknown"` category.38Advanced: KNN or iterative (MICE) imputation when features are39correlated. Drop rows only when < 5% are affected and missingness is40MCAR. Always fit imputers on training data only.4142### Feature scaling4344- **StandardScaler** (z-score) — linear regression, SVM, PCA45- **MinMaxScaler** (0–1) — neural networks, bounded range46 requirements; sensitive to outliers47- **RobustScaler** (IQR-based) — when outliers are present48- **No scaling needed** for tree-based models (Random Forest,49 XGBoost)5051Always fit on training data only and apply the same transform to52test data.5354### Feature selection5556Filter methods (correlation, mutual information, chi-square) are57fast but ignore interactions. Wrapper methods (RFE, forward/backward)58consider combinations but are expensive. Embedded methods (Lasso,59tree importance, permutation importance) are the best60speed/accuracy balance. Remove zero-variance features first. Drop61one of each highly correlated pair (r > 0.9). Use domain knowledge62as the first filter before data-driven methods.6364### Time-series features6566- **Lag features** — `value_lag_1`, `value_lag_7`, `value_lag_30`67 chosen by domain seasonality68- **Rolling statistics** — `value_rolling_mean_7d`, std, min, max69 over windows matching the pattern70- **Seasonal features** — `hour_of_day`, `day_of_week`, `month`,71 `is_weekend`, `is_holiday`; encode cyclical features as72 `sin(2*pi*hour/24)` and matching cosine73- **Difference features** — period-over-period change, percent change74- **Expanding statistics** — cumulative mean, sum, count7576Respect temporal ordering — never use future values as features.7778### Avoiding data leakage7980Never compute features using information from the test set. Fit all81transformers (scaler, imputer, encoder) on training data only. For82time series, features must use only data available at prediction83time. Target encoding must use cross-validation folds, never the84full training set. Wrap preprocessing in `sklearn.pipeline.Pipeline`85to enforce ordering.8687## Gotchas8889Agent-specific failure modes — provider-neutral pause-and-self-check items:9091- **Fitting transformers on the full dataset before splitting.** Fitting a scaler, imputer, or target encoder on train + test leaks test-set statistics into the model. Fit all transformers on training data only, then transform test data with the training-fitted transformer.92- **Target encoding without cross-validation.** Replacing a categorical with its mean target value on the same fold creates direct leakage: the model learns to associate the target with... the target. Use cross-validated target encoding where each fold is encoded using only the other folds' statistics.93- **Label-encoding nominal categories.** Label encoding implies an ordinal relationship (e.g., `Red=0, Blue=1, Green=2` implies `Green > Blue > Red`). Linear models and neural networks will learn a false ordering. Use one-hot or target encoding for nominals with no natural order.94- **Time-series features that peek at future data.** A lag-3 feature computed from row `t` includes data from rows `t+1`, `t+2`, `t+3` if the DataFrame is sorted descending. Verify temporal direction and always use only data available at prediction time.95- **Applying MinMaxScaler when the test set contains values outside the training range.** MinMaxScaler clips values to `[0, 1]` based on training min/max. Out-of-range test values produce values outside `[0, 1]` or are clipped, corrupting the distribution. Use RobustScaler or StandardScaler for data with outliers or uncertain ranges.96- **Polynomial feature expansion on all features "to be safe".** Degree-2 expansion on 100 features produces ~5,000 features. Most of these will be noise, increasing training time and overfitting risk dramatically. Use polynomial features only for specific known non-linear relationships.97- **Feature selection before splitting.** Running mutual information or correlation-based selection on the full dataset lets test-set information guide which features are retained. Select features using only training data, ideally inside a sklearn Pipeline.9899## Full reference100101### Text features102103- **TF-IDF** — baseline text representation; use `max_features` to104 cap dimensionality. Strong with traditional ML classifiers.105- **Count vectorizer** — simpler than TF-IDF when raw frequency is106 enough.107- **Embeddings** — pre-trained sentence-transformers for semantic108 similarity; superior for nuance, more expensive.109- **Extracted features** — text length, word count, punctuation110 count, sentiment score, readability. Often more interpretable111 than bag-of-words.112113Combine TF-IDF + extracted features for a strong baseline before114reaching for embeddings.115116### Interaction and derived features117118- Interaction terms for known relationships (`price * quantity =119 revenue`)120- Ratio features (`clicks / impressions`, `revenue / users`)121- Polynomial features sparingly (degree 2 max), only for known122 non-linear relationships123- Binning continuous → categorical when the relationship is124 step-wise (age groups, income brackets); use domain-driven bins,125 not arbitrary quantiles126- Log transform right-skewed features (income, prices, counts)127128### Worked examples129130- **user_id, city, purchase_amount, timestamp:** Cross-validated131 target encoding on city; extract day_of_week, hour, is_weekend132 from timestamp; lag features per user; rolling 7- and 30-day133 purchase means; days_since_last_purchase. Wrap in a sklearn134 Pipeline.135- **200 features, poor performance:** Drop zero-variance and136 near-constant columns, drop one of each correlated pair (r > 0.9),137 rank with permutation importance on the baseline, retrain on top138 30–50, compare. Audit remaining features for leakage.139- **40% missing income:** Investigate MAR via correlation with140 other features. Add `income_is_missing` indicator. Impute median141 from the training set (robust to skew). Compare model performance142 to KNN imputation as an alternative.143144### Anti-patterns145146- Fitting a scaler or encoder on the full dataset before splitting147- Target encoding without cross-validation (silent leakage)148- Label-encoding nominal categories149- Imputing nulls with column mean computed across train + test150- Time-series features that peek at future timestamps151- Polynomial expansion of every feature "to be safe"