Encoding Categorical Data
Models need numbers, so text categories must be converted to numeric form.
Syntax
pd.get_dummies(df, columns=['city'])scikit-learn models work on numbers, not text. Categorical columns like city must be encoded.
Two main techniques
- One-hot encoding — one 0/1 column per category. Best for unordered categories. Use
pd.get_dummies. - Label / ordinal encoding — map each category to an integer. Only for truly ordered categories (small < medium < large).
Example
import pandas as pd
df = pd.DataFrame({'city': ['Paris', 'Rome', 'Oslo', 'Rome']})
one_hot = pd.get_dummies(df, columns=['city'])
print(one_hot)
# city_Oslo city_Paris city_Rome
# 0 False True False
# 1 False False True
# 2 True False False
# 3 False False TrueWhen to use it
- An ML engineer one-hot encodes a country column with 50 unique values so a logistic regression model can use it as a feature.
- A data scientist uses label encoding for an ordinal education column (high school < bachelor < master < PhD) to preserve its order.
- A pipeline uses scikit-learn's OrdinalEncoder inside a ColumnTransformer to encode categoricals in a reproducible, fit-on-train-only manner.
More examples
One-hot encoding with pandas
Expands a three-category color column into three binary indicator columns using pd.get_dummies, the simplest one-hot approach.
import pandas as pd
df = pd.DataFrame({'color': ['red', 'blue', 'green', 'blue']})
encoded = pd.get_dummies(df, columns=['color'])
print(encoded)Label encoding for ordinal features
Encodes an education column with a meaningful order using OrdinalEncoder, so the model can treat it as an increasing numeric scale.
import pandas as pd
from sklearn.preprocessing import OrdinalEncoder
df = pd.DataFrame({'edu': ['high_school', 'bachelor', 'master', 'bachelor', 'phd']})
order = [['high_school', 'bachelor', 'master', 'phd']]
enc = OrdinalEncoder(categories=order)
df['edu_enc'] = enc.fit_transform(df[['edu']])
print(df)OneHotEncoder in a scikit-learn pipeline
Embeds OneHotEncoder into a scikit-learn Pipeline via ColumnTransformer so it is fit only on training data, preventing data leakage.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
X = pd.DataFrame({'gender': ['M','F','F','M'], 'age': [25,32,47,29]})
y = [0, 1, 1, 0]
ct = ColumnTransformer([
('ohe', OneHotEncoder(), ['gender']),
('pass', 'passthrough', ['age'])
])
pipe = Pipeline([('prep', ct), ('clf', LogisticRegression())])
pipe.fit(X, y)
Discussion