Machine Learning Academy · Урок

Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder

Вы преобразуете порядковые категории в целые числа, а номинальные категории — в one-hot-векторы, обрабатывая неизвестные категории во время применения модели

Урок 3 из 413 шагов

«Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder» — бесплатный урок Machine Learning Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Machine Learning Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Machine Learning Academy содержит 4 уроков всего.

Части этого урока еще не переведены и отображаются на английском.

Why Categorical Encoding Is Required

Machine learning models operate on numbers, not strings. A column containing values like 'red', 'green', 'blue' cannot be fed directly into a scikit-learn estimator. You must convert categories to numeric representations before training. The choice of encoding method matters greatly: a poor encoding can introduce spurious ordinal relationships or explode dimensionality. This lesson covers the two most important encoders: OrdinalEncoder for ordered categories and OneHotEncoder for unordered ones.

import pandas as pd

df = pd.DataFrame({
    'size': ['small', 'medium', 'large', 'medium'],
    'color': ['red', 'blue', 'green', 'red'],
    'price': [10.5, 20.0, 15.0, 18.5]
})

print(df.dtypes)
# size and color are 'object' (string) — must be encoded before modelling

Ordinal vs Nominal Categories

Not all categorical variables are equal. Ordinal categories have a meaningful order: small < medium < large, or bad < fair < good < excellent. Nominal categories have no intrinsic order: red, blue, green are just labels. Choosing the wrong encoding creates false relationships — for example, integer-encoding unordered colors as 0, 1, 2 tells the model that blue (1) is somehow between red (0) and green (2), which is meaningless. Always identify whether a variable is ordinal or nominal before encoding.

# Ordinal: clear ordering
ordinal_example = ['low', 'medium', 'high', 'very high']

# Nominal: no meaningful ordering
nominal_example = ['cat', 'dog', 'bird']

# Wrong approach for nominal: integer encoding implies order
# 0=cat, 1=dog, 2=bird -- model thinks dog is between cat and bird

# Correct approach for nominal: one-hot encoding
# cat -> [1, 0, 0]
# dog -> [0, 1, 0]
# bird -> [0, 0, 1]

OrdinalEncoder: Mapping Order to Integers

OrdinalEncoder maps each category to an integer based on a specified order. You provide the categories parameter as a list of lists, where the position determines the integer assigned. If you do not specify order, scikit-learn assigns integers alphabetically — which may or may not align with true order. Always specify the category order explicitly for ordinal variables to ensure the model captures the correct relationship between values.

from sklearn.preprocessing import OrdinalEncoder
import numpy as np

X = np.array([['low'], ['high'], ['medium'], ['low'], ['high']])

# Specify order explicitly: low=0, medium=1, high=2
enc = OrdinalEncoder(categories=[['low', 'medium', 'high']])
X_encoded = enc.fit_transform(X)

print('Ordinal encoded:', X_encoded.flatten())
# [0. 2. 1. 0. 2.]

OneHotEncoder: Dummy Variables for Nominal Data

OneHotEncoder creates one binary column per category. For a color feature with values red, green, blue, it produces three columns: color_red, color_green, color_blue, where exactly one is 1 and the rest are 0 for each row. This avoids any implied ordering. The trade-off is dimensionality: a feature with 100 unique values creates 100 new columns. By default, scikit-learn's OneHotEncoder drops one category (dummy encoding) to avoid perfect multicollinearity in linear models.

from sklearn.preprocessing import OneHotEncoder
import numpy as np

X = np.array([['red'], ['green'], ['blue'], ['red']])

enc = OneHotEncoder(sparse_output=False)  # dense output for readability
X_ohe = enc.fit_transform(X)

print('Categories:', enc.categories_)
print('One-hot encoded:\n', X_ohe)
# [[0. 0. 1.]
#  [0. 1. 0.]
#  [1. 0. 0.]
#  [0. 0. 1.]]

Dropping One Category: Dummy Encoding

When using OneHotEncoder with linear models, keeping all K columns for a K-category variable introduces perfect multicollinearity — the columns sum to 1, so any one column is a linear combination of the others. This makes the design matrix singular (non-invertible). Setting drop='first' drops the first category, leaving K-1 columns that fully describe the variable without redundancy. For tree-based models, keeping all K columns is harmless and sometimes slightly better, so you can use drop=None.

from sklearn.preprocessing import OneHotEncoder
import numpy as np

X = np.array([['red'], ['green'], ['blue'], ['red']])

# Drop first category to avoid multicollinearity
enc = OneHotEncoder(drop='first', sparse_output=False)
X_ohe = enc.fit_transform(X)

print('Categories kept (first dropped):', enc.get_feature_names_out())
print('Encoded:\n', X_ohe)
# Only 2 columns instead of 3

Handling Unknown Categories at Inference

A real-world challenge: at inference time, a category may appear that was not in the training data. By default, OrdinalEncoder and OneHotEncoder raise an error on unknown categories. Set handle_unknown='ignore' in OneHotEncoder to produce all-zero rows for unknown values (the model predicts without that feature). For OrdinalEncoder, set handle_unknown='use_encoded_value' with unknown_value=-1 to flag unknowns explicitly.

from sklearn.preprocessing import OneHotEncoder
import numpy as np

# Training data: only red and blue seen
X_train = np.array([['red'], ['blue'], ['red']])
X_test  = np.array([['green']])  # Unseen at training time

enc = OneHotEncoder(handle_unknown='ignore', sparse_output=False)
enc.fit(X_train)

X_test_enc = enc.transform(X_test)
print('Unknown category encodes as all zeros:', X_test_enc)
# [[0. 0.]] -- no error, unknown silently encoded as zeros

Target Encoding for High Cardinality Features

When a categorical feature has hundreds or thousands of unique values (e.g., zip codes, product SKUs), one-hot encoding creates an unmanageably large matrix. Target encoding replaces each category with the mean of the target variable for that category. This compresses high-cardinality features to a single column. The risk is target leakage: if you encode using the mean computed on the same rows you train on, the model memorises patterns rather than generalising. Always use cross-fold target encoding to prevent leakage.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'city': ['NYC', 'LA', 'NYC', 'Chicago', 'LA', 'NYC'],
    'churned': [1, 0, 1, 0, 1, 0]
})

# Simple (leaky) target encoding
target_mean = df.groupby('city')['churned'].mean()
df['city_encoded'] = df['city'].map(target_mean)
print(df[['city', 'city_encoded', 'churned']])
# Use cross-fold encoding in practice to avoid leakage

Binary Encoding for Medium Cardinality

Binary encoding is a middle ground between ordinal and one-hot encoding. Each integer code is converted to its binary representation, producing log2(K) columns instead of K columns. For example, 8 categories need only 3 binary columns instead of 8 one-hot columns. This reduces dimensionality significantly for features with 10–100 categories. The category_encoders library provides BinaryEncoder that handles this transformation with a scikit-learn compatible API.

# Conceptual example: binary encoding manually
# Category -> Integer -> Binary columns
categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']

for i, cat in enumerate(categories):
    binary = format(i, '03b')  # 3 bits for 8 categories
    print(f'{cat} -> {i} -> {list(binary)}')

# A -> 0 -> [0, 0, 0]
# B -> 1 -> [0, 0, 1]
# ...
# H -> 7 -> [1, 1, 1]
# 8 categories need only 3 columns (vs 8 with one-hot)

Applying Encoders in ColumnTransformer

Real datasets have a mix of numeric, ordinal, and nominal columns. ColumnTransformer applies different transformations to different columns in parallel and concatenates the results. Specify ordinal columns with OrdinalEncoder, nominal columns with OneHotEncoder, and numeric columns with StandardScaler. The output is a single clean numeric matrix ready for any scikit-learn estimator. This is the standard production pattern for mixed-type datasets.

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OrdinalEncoder, OneHotEncoder, StandardScaler

preprocessor = ColumnTransformer([
    ('num', StandardScaler(), ['age', 'income']),
    ('ord', OrdinalEncoder(categories=[['low', 'medium', 'high']]), ['risk_level']),
    ('nom', OneHotEncoder(drop='first', sparse_output=False), ['city', 'product'])
])

# Result: numeric + ordinal encoded + one-hot columns in one matrix

Feature Names After Encoding

After encoding, your feature matrix has more columns than the original DataFrame, and scikit-learn transformers track the new names. Call get_feature_names_out() on ColumnTransformer or OneHotEncoder to retrieve the generated feature names. This is essential for model interpretability: knowing which one-hot column corresponds to which original category lets you correctly interpret feature importances from Random Forests or SHAP values from gradient boosting models.

from sklearn.preprocessing import OneHotEncoder
import numpy as np

X = np.array([['red', 'small'], ['blue', 'large'], ['green', 'medium']])

enc = OneHotEncoder(sparse_output=False)
enc.fit(X)

print('Feature names:', enc.get_feature_names_out(['color', 'size']))
# ['color_blue' 'color_green' 'color_red' 'size_large' 'size_medium' 'size_small']

X_enc = enc.transform(X)
print('Encoded shape:', X_enc.shape)

Full Encoding Pipeline: End-to-End Example

Here is a complete pipeline with mixed encoding. ColumnTransformer handles three column types: numerical features are scaled, an ordinal feature is integer-encoded with explicit order, and nominal features become one-hot columns. The pipeline is then cross-validated — encoding is refitted within each CV fold to prevent leakage. This pattern works for any dataset and is ready for deployment once trained on the full dataset.

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OrdinalEncoder, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

preprocessor = ColumnTransformer([
    ('num', StandardScaler(), ['age', 'income']),
    ('ord', OrdinalEncoder(categories=[['low', 'medium', 'high']]), ['risk']),
    ('ohe', OneHotEncoder(drop='first', handle_unknown='ignore'), ['city'])
])

pipeline = Pipeline([
    ('prep', preprocessor),
    ('clf', LogisticRegression(max_iter=500))
])

scores = cross_val_score(pipeline, X, y, cv=5, scoring='accuracy')
print('CV accuracy:', scores.mean().round(3))

Quick Check

Test your understanding of Machine Learning with Python concepts from this lesson.

Lesson Recap

In this lesson you learned: the difference between ordinal and nominal categories and why it determines encoding choice, OrdinalEncoder for ordered variables and OneHotEncoder for nominal variables, and how to handle unknown categories and combine encoders in a ColumnTransformer pipeline. Next up we explore combining all preprocessing steps with ColumnTransformer.

Можно начать бесплатно

Изучай Python с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
30
Уроки
120

Часто задаваемые вопросы

Урок «Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder» бесплатный?

Да — полный текст урока «Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Machine Learning Academy, подпишись на CoddyKit PRO. Курс Machine Learning Academy содержит 4 уроков всего.

Чему я научусь в уроке «Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder»?

Вы преобразуете порядковые категории в целые числа, а номинальные категории — в one-hot-векторы, обрабатывая неизвестные категории во время применения модели Ты практикуешь Machine Learning Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Machine Learning Academy?

Предыдущий опыт не требуется. Machine Learning Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Machine Learning Academy?

Да. Каждый урок Machine Learning Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Обработка пропущенных значений: удаление, заполнение и маркировка
  2. Масштабирование признаков: StandardScaler и MinMaxScaler
  3. Кодирование категориальных переменных: OrdinalEncoder и OneHotEncoder
  4. Объединение этапов с помощью ColumnTransformer
← Назад к Machine Learning Academy