Pandas get_dummies (One-Hot кодирование), объяснение

Функция pd.get_dummies() из библиотеки Pandas позволяет легко выполнять one-hot кодирование категориальных данных. В этом руководстве вы узнаете, как работает функция get_dummies() в Pandas и как настраивать её поведение. One-hot кодирование — это распространённый этап предобработки данных при работе с категориальными переменными в машинном обучении.

Если вы планируете интегрировать one-hot кодирование в рабочий процесс с использованием scikit-learn, возможно, вам стоит рассмотреть класс OneHotEncoder из библиотеки scikit-learn!

К концу этого урока вы узнаете:

  • Что такое one-hot кодирование и зачем оно нужно

  • Как использовать функцию pd.get_dummies() для one-hot кодирования данных

  • Как кодировать несколько столбцов с помощью get_dummies()

  • Как настраивать названия новых закодированных столбцов

  • Как обрабатывать пропущенные значения при использовании get_dummies

Оглавление

Понимание one-hot кодирования в машинном обучении

One-hot кодирование — важный шаг подготовки данных для использования в алгоритмах машинного обучения. Оно преобразует категориальные данные в бинарное (нули и единицы) числовое представление, понятное моделям машинного обучения.

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

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

См. изображение ниже для визуального представления процесса:

One-Hot-Encoding-for-Scikit-Learn-in-Python-Explained
Понимание прямого кодирования категориальных данных

Вы можете спросить: почему бы просто не преобразовать значения в числа, например, присвоив {'Biscoe': 1, 'Torgensen': 2, 'Dream': 3}? Такой подход предполагает, что между значениями существует определённый порядок или числовая зависимость. Например, разница между Biscoe и Dream будет считаться большей, чем между Biscoe и Torgensen.

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

Однако, если ваши данные порядковые (ordinal), то есть имеют чёткий порядок (например, размеры одежды: Small < Medium < Large), то такой способ кодирования может быть оправдан.

Какие недостатки у one-hot кодирования?

One-hot кодирование очень полезно при работе с категориальными переменными. Однако у него есть один серьёзный недостаток — оно значительно увеличивает количество данных. Для каждой уникальной категории создаётся новый столбец, что может привести к резкому росту размерности набора данных.

Из-за этого one-hot кодирование не рекомендуется использовать, если категорий слишком много (high cardinality).

Загрузка примера набора данных

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

# Загрузка примера DataFrame

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

print(df)

# Возвращает:
#       Name  Gender     House Type
# 0     Joan  Female      Apartment
# 1     Matt    Male       Detached
# 2     Jeff    Male      Apartment
# 3  Melissa  Female           None
# 4     Devi  Female  Semi-Detached

В приведённом выше коде мы загрузили DataFrame с тремя столбцами: Name, Gender и House Type. Столбцы Gender и House Type содержат категориальные данные. Теперь, когда у нас есть DataFrame, давайте перейдём к изучению функции pd.get_dummies().

Понимание функции Pandas get_dummies

Прежде чем переходить к использованию функции pd.get_dummies(), важно разобраться в её синтаксисе. Это поможет вам лучше понимать, какой результат вы получите, и как настроить работу функции под свои нужды.

Давайте посмотрим, из чего состоит функция pd.get_dummies():

# Понимание функции get_dummies в Pandas

import pandas as pd

# Преобразование категориальных переменных в фиктивные/индикаторные переменные.

# Аргументы:
# data: array-like, Series или DataFrame. Данные для кодирования.
# prefix: str, list of str, или dict of str, необязательный. Префикс(ы) для имен столбцов фиктивных переменных.
# prefix_sep: str, по умолчанию '_'. Разделитель между префиксом и именем исходной переменной.
# dummy_na: bool, по умолчанию False. Указывает, следует ли создавать отдельный столбец для значений NaN.
# columns: list-like, необязательный. Названия столбцов в DataFrame для кодирования. По умолчанию кодируются все столбцы с object или category dtype.
# sparse: bool, по умолчанию False. Указывает, возвращать ли разреженную матрицу.
# drop_first: bool, по умолчанию False. Указывает, следует ли удалять первую категорию в каждом признаке. Полезно для избежания мультиколлинеарности.
# dtype: dtype, необязательный. Тип данных для новых столбцов.

pd.get_dummies(
    data,
    prefix=None,
    prefix_sep='_',
    dummy_na=False,
    columns=None,
    sparse=False,
    drop_first=False,
    dtype=None
)

Мы можем видеть, что функция предлагает большое количество параметров! Давайте разберём, за что отвечает каждый из них:

  • data= — данные, на основе которых создаются фиктивные переменные (может быть массивом, объектом Pandas Series или DataFrame)

  • prefix= — строка, которую нужно добавить к названиям новых столбцов

  • prefix_sep= — разделитель между префиксом и значением при формировании новых заголовков

  • dummy_na= — добавлять ли отдельный столбец для пропущенных значений (NaN)

  • columns= — список столбцов, которые нужно кодировать (если передан DataFrame)

  • sparse= — использовать ли разрежённое представление данных (экономия памяти)

  • drop_first= — удалять ли первый уровень (для предотвращения мультиколлинеарности)

  • dtype= — тип данных для новых столбцов (например, int, float и т. д.)

Теперь, когда вы хорошо понимаете параметры функции pd.get_dummies(), давайте рассмотрим, как использовать эту функцию для one-hot кодирования ваших данных.

Как использовать функцию pd.get_dummies() в Pandas

В предыдущем разделе вы узнали о доступных параметрах функции pd.get_dummies(). В этом разделе вы научитесь применять её для one-hot кодирования данных. Единственный обязательный параметр — это data=, который принимает либо объект Series, либо целый DataFrame.

Давайте посмотрим, что происходит, если мы передаём в параметр data= один столбец:

# One-Hot кодирование отдельной Series DataFrame

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

print(pd.get_dummies(df['Gender']))

# Возвращает:
#    Female  Male
# 0       1     0
# 1       0     1
# 2       0     1
# 3       1     0
# 4       1     0

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

Давайте посмотрим, как можно передать в параметр data= целый DataFrame и выполнить one-hot кодирование только для одного столбца:

# One-Hot кодирование с возвратом DataFrame

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

# Применение one-hot кодирования к столбцу 'Gender'
ohe = pd.get_dummies(data=df, columns=['Gender'])
print(ohe)

# Возвращает:
#       Name     House Type  Gender_Female  Gender_Male
# 0     Joan      Apartment              1            0
# 1     Matt       Detached              0            1
# 2     Jeff      Apartment              0            1
# 3  Melissa           None              1            0
# 4     Devi  Semi-Detached              1            0

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

Работа с пропущенными данными при использовании get_dummies в Pandas

В этом разделе вы узнаете, как обрабатывать пропущенные значения при выполнении one-hot кодирования с помощью функции pd.get_dummies().

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

Это также касается и one-hot кодирования — по умолчанию функция pd.get_dummies() игнорирует пропущенные значения. Давайте посмотрим, как это проявляется при кодировании столбца House Type:

# One-Hot кодирование столбца с пропущенными данными

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

# Применение one-hot кодирования к столбцу 'House Type'
ohe = pd.get_dummies(df['House Type'])
print(ohe)

# Возвращает:
#    Apartment  Detached  Semi-Detached
# 0          1         0              0
# 1          0         1              0
# 2          1         0              0
# 3          0         0              0
# 4          0         0              1

В приведённом выше блоке кода мы выполнили one-hot кодирование столбца House Type, в котором было пропущенное значение на позиции индекса 3. Мы можем видеть, что ни один из новых закодированных столбцов не содержит значения для этой строки.

Это поведение можно изменить, включив обработку пропущенных значений с помощью параметра dummy_na=, который по умолчанию установлен в False. Давайте установим это значение в True и посмотрим, как изменится результат:

# One-Hot кодирование столбцов с пропущенными данными

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

# Применение one-hot кодирования к столбцу 'House Type' с включением столбца для NaN
ohe = pd.get_dummies(df['House Type'], dummy_na=True)
print(ohe)

# Возвращает:
#    Apartment  Detached  Semi-Detached  NaN
# 0          1         0              0    0
# 1          0         1              0    0
# 2          1         0              0    0
# 3          0         0              0    1
# 4          0         0              1    0

Мы можем видеть, что теперь добавлен новый столбец, обозначающий наличие пропущенных данных в этом поле.

One-Hot кодирование нескольких столбцов с помощью get_dummies в Pandas

В этом разделе вы узнаете, как выполнить one-hot кодирование сразу нескольких столбцов с помощью функции pd.get_dummies().

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

Для этого достаточно передать DataFrame в параметр data=, а в параметр columns= указать список столбцов, которые вы хотите закодировать. Давайте посмотрим, как это работает:

# One-Hot кодирование нескольких столбцов с помощью Pandas get_dummies()

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

# Применение one-hot кодирования к столбцам 'Gender' и 'House Type'
ohe = pd.get_dummies(data=df, columns=['Gender', 'House Type'])
print(ohe)

# Возвращает:
#       Name  Gender_Female  Gender_Male  House Type_Apartment  House Type_Detached  House Type_Semi-Detached
# 0     Joan              1            0                     1                    0                         0
# 1     Matt              0            1                     0                    1                         0
# 2     Jeff              0            1                     1                    0                         0
# 3  Melissa              1            0                     0                    0                         0
# 4     Devi              1            0                     0                    0                         1

Мы можем видеть, насколько просто выполнять one-hot кодирование нескольких столбцов с помощью функции pd.get_dummies().

Изменение разделителя в названиях закодированных столбцов в Pandas get_dummies

Pandas также позволяет легко изменить символ-разделитель, используемый при формировании названий новых столбцов после one-hot кодирования. По умолчанию используется символ подчёркивания _, чтобы отделить префикс от значения переменной. Это поведение можно изменить с помощью параметра prefix_sep=.

В приведённом выше примере мы увидели, что столбец 'House Type' содержал пробел. По этой причине использование символа подчёркивания выглядит немного неуклюже. Давайте изменим разделитель на пробел:

# Изменение разделителя префикса в Pandas get_dummies()

import pandas as pd

df = pd.DataFrame({
    'Name': ['Joan', 'Matt', 'Jeff', 'Melissa', 'Devi'],
    'Gender': ['Female', 'Male', 'Male', 'Female', 'Female'],
    'House Type': ['Apartment', 'Detached', 'Apartment', None, 'Semi-Detached']
    })

# Изменение разделителя префикса на пробел
ohe = pd.get_dummies(data=df, columns=['House Type'], prefix_sep=' ')
print(ohe)

# Возвращает:
#       Name  Gender  House Type Apartment  House Type Detached  House Type Semi-Detached
# 0     Joan  Female                     1                    0                         0
# 1     Matt    Male                     0                    1                         0
# 2     Jeff    Male                     1                    0                         0
# 3  Melissa  Female                     0                    0                         0
# 4     Devi  Female                     0                    0                         1

Заключение

В этом руководстве вы узнали, как выполнять one-hot кодирование данных с помощью функции pd.get_dummies() в Pandas. Вы ознакомились с тем, что такое one-hot кодирование и как оно используется в машинном обучении. Также вы научились:

  • Применять get_dummies() для кодирования отдельных и нескольких столбцов,

  • Включать пропущенные значения в процесс кодирования с помощью параметра dummy_na=,

  • Настройка разделителей и префиксов новых столбцов с помощью параметров prefix= и prefix_sep=,

  • Интегрировать результаты обратно в исходный DataFrame.

Теперь вы можете эффективно обрабатывать категориальные данные для использования в моделях машинного обучения.


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

Вопрос: Что лучше использовать — pd.get_dummies или OneHotEncoder из Scikit-Learn?

Ответ: Оба метода выполняют one-hot кодирование, но OneHotEncoder из Scikit-Learn интегрируется в ML-пайплайны и позволяет применять одинаковое кодирование к обучающим и тестовым данным. Это особенно важно при развертывании моделей. Однако

Вопрос: В чём разница между one-hot encoding и dummy encoding?

Ответ: One-hot кодирование создаёт n новых столбцов для n уникальных значений, тогда как dummy кодирование создаёт n-1 столбец, чтобы избежать мультиколлинеарности. В Pandas по умолчанию используется one-hot кодирование, но его можно изменить, установив drop_first=True.


Дополнительные ресурсы

Чтобы углубить свои знания, ознакомьтесь со следующими материалами:

Last updated