Most estimators accept only numbers, and real tabular data is full of categories.
Columns such as city or plan hold categories, which most estimators cannot use directly. Two encoders cover most needs.
OneHotEncoder creates one 0/1 column per category. It makes no assumption of order, so it is the safe default for nominal features with a modest number of categories. Key options:
handle_unknown="ignore": a category not seen in training becomes all zeros instead of raising an error. Use"infrequent_if_exist"together withmin_frequencyormax_categoriesto group rare categories.sparse_output=False: return a dense array (the default is a sparse matrix).drop="if_binary"ordrop="first": avoid a redundant column, mostly useful for unregularised linear models.
get_feature_names_out() tells you the names of the generated columns, like city_Paris.
OrdinalEncoder maps categories to integers 0, 1, 2... It is compact and suits tree-based models, or genuinely ordered categories when you pass the order via categories=[["low", "mid", "high"]]. For linear models, arbitrary integer codes imply a false ordering.
LabelEncoder is meant for the target y, not for features. Like scalers, encoders must be fitted on the training data, ideally inside a pipeline.
Example
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder
train = pd.DataFrame({"city": ["Paris", "Rome", "Paris", "Oslo"],
"size": ["S", "L", "M", "S"]})
test = pd.DataFrame({"city": ["Rome", "Lima"], "size": ["M", "L"]})
ohe = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
ohe.fit(train[["city"]])
print(ohe.get_feature_names_out()) # ['city_Oslo' 'city_Paris' 'city_Rome']
print(ohe.transform(test[["city"]])) # Lima is unseen -> all zeros
# [[0. 0. 1.]
# [0. 0. 0.]]
ord_enc = OrdinalEncoder(categories=[["S", "M", "L"]])
print(ord_enc.fit_transform(train[["size"]]).ravel()) # [0. 2. 1. 0.]Remember
- One-hot for nominal categories, ordinal for ordered ones or for trees
handle_unknown="ignore"keeps prediction working on unseen categoriesLabelEncoderis for targets, not features
Watch out for
- Using
pd.get_dummiesseparately on train and test, which can produce different columns.