Fit preprocessing on training data, every time.
from sklearn.compose import make_column_transformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
prep = make_column_transformer(
(SimpleImputer(strategy="median"), numeric_columns),
(OneHotEncoder(handle_unknown="ignore"), categorical_columns),
)
model = make_pipeline(prep, LogisticRegression(max_iter=1000))
A pipeline fits transforms only on each training partition, then applies them unchanged to held-out rows. This prevents preprocessing leakage and keeps training and prediction steps together.[1]
Median imputation supplies missing numeric values. One-hot encoding turns categories into indicator columns. handle_unknown="ignore" allows a category unseen during training without crashing prediction.
Study scikit-learn’s mixed-types ColumnTransformer example.