Импутация - это процесс замены отсутствующих данных статистическими оценками отсутствующих значений. Цель любого метода вменения - создать полный набор данных, который можно использовать для обучения моделей машинного обучения.

Вменение режима состоит в замене всех вхождений пропущенных значений (NA) в переменной на режим, который, другими словами, относится к наиболее частому значению или наиболее частой категории .

Какие переменные можно вычислить с помощью наиболее частого / режима вменения?

Хотя режим или наиболее частое значение можно вычислить как для числовых, так и для категориальных переменных, на практике мы используем этот метод только для категориальных переменных. Причина в том, что для числовых переменных среднее значение или медиана, как правило, лучше представляют среднее значение для генеральной совокупности.

Когда использовать режим / наиболее частое вменение категорий?

Данные отсутствуют случайно.
Не более 5% переменной содержат отсутствующие данные.

Преимущества

Его легко реализовать.
Это быстрый способ получения полных наборов данных.
Его можно интегрировать в производственную среду (во время развертывания модели).

Ограничения

Это искажает связь наиболее часто встречающейся метки с другими переменными в наборе данных.
Это может привести к чрезмерному представлению наиболее часто встречающейся метки, если имеется большое количество NA.

Демонстрация приведения отсутствующих значений в режим.

Мы будем использовать набор данных о ценах на жилье, чтобы продемонстрировать, как выполнять условное исчисление в категориальных переменных.

Чтобы загрузить набор данных, обратитесь к: « Набор данных о ценах на жилье »

Импорт необходимых библиотек:

import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt 
# To split the datasets
from sklearn.model_selection import train_test_split

Определение используемых столбцов:

BsmtQual: оценивает высоту подвала. (Категориальная переменная)

FireplaceQu: качество камина. (Категориальная переменная)

# Defining columns to use from the house price dataset
cols_to_use = ['BsmtQual', 'FireplaceQu', 'SalePrice']
# Reading the dataset using pandas 
data = pd.read_csv('../houseprice.csv', usecols=cols_to_use)
data.head()

Вывод:

У нас отсутствуют данные?

# let's inspect the percentage of missing values in each variable
data.isnull().mean()
BsmtQual       0.025342
FireplaceQu    0.472603
SalePrice      0.000000
dtype: float64

Переменная BsmtQual содержит только несколько наблюдений с NA (2,5%), поэтому замена этих наблюдений значением наиболее часто встречающейся категории - хороший подход.

С другой стороны, переменная FireplaceQu содержит недостающие данные почти в (47,26%) половине наблюдений. Следовательно, замена категорий наиболее часто встречающейся категорией, скорее всего, приведет к искажению связи наиболее часто встречающейся категории с продажной ценой.

Важное замечание:

Величина должна выполняться по обучающему набору, а затем распространяться на тестовый набор. Это означает, что из обучающего набора необходимо выбрать наиболее частую категорию и использовать ее для замены NA как в обучающей, так и в тестовой выборках.

Разделение на набор данных для обучения и тестирования:

# let's separate into training and testing set
X_train, X_test, y_train, y_test = train_test_split(
    data,
    data['SalePrice'], # target
    test_size=0.3, # percentage of observations in the test set
    random_state=0)

BsmtQual (качество подвала):

Напомним процент пропущенных значений.

X_train['BsmtQual'].isnull().mean()
0.023483365949119372         

Давайте проверим количество наблюдений для каждой категории в BsmtQual.

# value_counts() counts the amount of houses that show each of the labels in the variable indicated below
X_train['BsmtQual'].value_counts().sort_values(ascending=False).plot.bar()
plt.xlabel('BsmtQual')
plt.ylabel('Number of houses')

Давайте найдем наиболее часто используемую категорию для BsmtQual.

X_train['BsmtQual'].mode()

0    TA
dtype: object

Наблюдения. Наиболее частая категория в BsmtQual - это TA ( Среднее / Типичное ).

Построение распределений целевой переменной относительно BsmtQual.

fig = plt.figure()
ax = fig.add_subplot(111)
# select and plot houses with the most frequent label
X_train[X_train[‘BsmtQual’]==’TA’][‘SalePrice’].plot(kind=’kde’, ax=ax)
# select and plot houses with missing data in the variable
X_train[X_train[‘BsmtQual’].isnull()][‘SalePrice’].plot(kind=’kde’, ax=ax, color=’red’)
# add the legend
lines, labels = ax.get_legend_handles_labels()
labels = [‘Houses with TA’, ‘Houses with NA’]
ax.legend(lines, labels, loc=’best’)
# add figure title
plt.title(‘BsmtQual’)

График выше показывает, что дома с отсутствующими данными стоят в целом меньше, чем дома с меткой TA. Следовательно, замена отсутствующих значений на TA может повлиять на общее распределение, если бы было много NA.

Давайте оставим исходное распределение SalePrice для наиболее часто встречающейся категории для дальнейшего использования.

# the use of tmp is common to name temporal variables
tmp = X_train[X_train['BsmtQual']=='TA']['SalePrice']

Давайте заполним NA как для обучения, так и для тестирования с помощью категории часто используемых.

# inplace=True is used to replicate that in original dataframe
X_train['BsmtQual'].fillna('TA', inplace=True)
X_test['BsmtQual'].fillna('TA', inplace=True)

Оценка влияния на распределение категорий.

X_train['BsmtQual'].value_counts().sort_values(ascending=False).plot.bar()
plt.xlabel('BsmtQual')
plt.ylabel('Number of houses')

Из приведенного выше графика мы видим, что теперь есть еще несколько домов с меткой TA, которые раньше содержали NA, но общее влияние на распределение не является драматическим. График выглядит почти идентично тому, что было до вменения.

Изменилось ли распределение SalePrice для наиболее частой категории?

fig = plt.figure()
ax = fig.add_subplot(111)
# original distribution of salePrice for houses with most frequent label
# remember I captured this a few cells up in the notebook
tmp.plot(kind='kde', ax=ax)
# distribution of the variable after imputation
X_train[X_train['BsmtQual'] == 'TA']['SalePrice'].plot(
    kind='kde', ax=ax, color='red')
# add the legend
lines, labels = ax.get_legend_handles_labels()
labels = ['Original variable', 'Imputed variable']
ax.legend(lines, labels, loc='best')
# add title
plt.title('BsmtQual')

Распределение цен на жилье между исходной и условно исчисленной переменной очень похоже, потому что количество отсутствующих данных было небольшим. Поэтому частое вменение категорий - хороший выбор для функции BsmtQual.

FirePlaceQu (качество камина):

Напомним процент пропущенных значений.

X_train['FireplaceQu'].isnull().mean()
0.46771037181996084

Давайте найдем наиболее часто используемую категорию для FirePlaceQu.

X_train['FireplaceQu'].mode()

0    Gd
dtype: object

Наблюдения. Самая частая категория в FirePlaceQu - Gd (хорошо).

Построим график распределения целевого объекта для домов, которые показывают наиболее частую категорию, и тех, для которых данные отсутствуют.

fig = plt.figure()
ax = fig.add_subplot(111)
# houses with the most frequent label for FirePlaceQu
X_train[X_train['FireplaceQu']=='Gd']['SalePrice'].plot(kind='kde', ax=ax)
# houses with missing data in FirePlaceQu
X_train[X_train['FireplaceQu'].isnull()]['SalePrice'].plot(kind='kde', ax=ax, color='red')
# add the legend
lines, labels = ax.get_legend_handles_labels()
labels = ['Houses with Gd', 'Houses with NA']
ax.legend(lines, labels, loc='best')
plt.title('FirePlaceQu')

Наблюдения:

Распределения совершенно разные: дома с отсутствующими данными стоят в целом меньше, чем дома с меткой Gd.

Давайте сохраним исходное распределение SalePrice, поскольку оно относится к наиболее частой категории для дальнейшего использования.

tmp = X_train[X_train['FireplaceQu']=='Gd']['SalePrice']

Давайте заполним NA как на тренировке, так и на тесте.

X_train['FireplaceQu'].fillna('Gd', inplace=True)
X_test['FireplaceQu'].fillna('Gd', inplace=True)

Построим график распределения целевой переменной
и вмененной переменной
.

fig = plt.figure()
ax = fig.add_subplot(111)
# original distribution of the variable
tmp.plot(kind='kde', ax=ax)
# distribution of the variable after imputation
X_train[X_train['FireplaceQu'] == 'Gd']['SalePrice'].plot(
    kind='kde', ax=ax, color='red')
# add the legend
lines, labels = ax.get_legend_handles_labels()
labels = ['Original variable', 'Imputed variable']
ax.legend(lines, labels, loc='best')
plt.title('FirePlaceQu')

Наблюдения:

Средняя стоимость дома для наиболее часто встречающейся категории значительно снизилась после добавления значений стоимости дома в NA после изменения категории NA в качестве наиболее часто используемого ярлыка.

В подобных случаях, когда процент пропущенных значений очень высок (~ 50%), лучше создать новую категорию (Отсутствует), чтобы заключить наблюдения с NA.

Полный исходный код можно найти здесь:

Https://github.com/ku-nal/Feature-Engineering/tree/main/Frequent-Category-Imputation

Надеюсь, это была полезная статья. Если у вас есть комментарии, не стесняйтесь записывать их ниже. Вы можете подписаться на меня на medium, linkedin.