Get_dummies Панды против OneHotEncoder() Sklearn ():: Что является более эффективным?
Я изучаю различные методы преобразования категориальных переменных в числовые для классификаторов машинного обучения. Я наткнулся на pd.get_dummies
метод и sklearn.preprocessing.OneHotEncoder()
и я хотел посмотреть, как они отличаются с точки зрения производительности и использования.
Я нашел учебник о том, как использовать OneHotEnocder()
на https://xgdgsc.wordpress.com/2015/03/20/note-on-using-onehotencoder-in-scikit-learn-to-work-on-categorical-features/ так как sklearn
документация не была слишком полезна для этой функции. У меня такое чувство, что я делаю это неправильно... но
Могут ли некоторые объяснить плюсы и минусы использования pd.dummies
над sklearn.preprocessing.OneHotEncoder()
и наоборот? я знаю это OneHotEncoder()
дает вам разреженную матрицу, но кроме этого я не уверен, как она используется и каковы преимущества по сравнению с pandas
метод. Я использую это неэффективно?
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
sns.set()
%matplotlib inline
#Iris Plot
iris = load_iris()
n_samples, m_features = iris.data.shape
#Load Data
X, y = iris.data, iris.target
D_target_dummy = dict(zip(np.arange(iris.target_names.shape[0]), iris.target_names))
DF_data = pd.DataFrame(X,columns=iris.feature_names)
DF_data["target"] = pd.Series(y).map(D_target_dummy)
#sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
#0 5.1 3.5 1.4 0.2
#1 4.9 3.0 1.4 0.2
#2 4.7 3.2 1.3 0.2
#3 4.6 3.1 1.5 0.2
#4 5.0 3.6 1.4 0.2
#5 5.4 3.9 1.7 0.4
DF_dummies = pd.get_dummies(DF_data["target"])
#setosa versicolor virginica
#0 1 0 0
#1 1 0 0
#2 1 0 0
#3 1 0 0
#4 1 0 0
#5 1 0 0
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
def f1(DF_data):
Enc_ohe, Enc_label = OneHotEncoder(), LabelEncoder()
DF_data["Dummies"] = Enc_label.fit_transform(DF_data["target"])
DF_dummies2 = pd.DataFrame(Enc_ohe.fit_transform(DF_data[["Dummies"]]).todense(), columns = Enc_label.classes_)
return(DF_dummies2)
%timeit pd.get_dummies(DF_data["target"])
#1000 loops, best of 3: 777 µs per loop
%timeit f1(DF_data)
#100 loops, best of 3: 2.91 ms per loop
5 ответов
OneHotEncoder
не может обрабатывать строковые значения напрямую. Если ваши номинальные характеристики являются строками, то вам нужно сначала отобразить их в целые числа.
pandas.get_dummies
вроде как наоборот. По умолчанию он преобразует только строковые столбцы в одно горячее представление, если столбцы не указаны.
Для машинного обучения вы почти наверняка захотите использовать sklearn.OneHotEncoder
. Для других задач, таких как простой анализ, вы можете использоватьpd.get_dummies
, что немного удобнее.
Обратите внимание, что sklearn.OneHotEncoder
был обновлен в последней версии, так что он принимает строки для категориальных переменных, а также целые числа.
Суть в том, что sklearn
Encoder создает функцию, которая сохраняется и затем может применяться к новым наборам данных, которые используют те же категориальные переменные, с согласованными результатами.
from sklearn.preprocessing import OneHotEncoder
# Create the encoder.
encoder = OneHotEncoder(handle_unknown="ignore")
encoder.fit(X_train) # Assume for simplicity all features are categorical.
# Apply the encoder.
X_train = encoder.transform(X_train)
X_test = encoder.transform(X_test)
Обратите внимание, как мы применяем тот же кодировщик, который мы создали через X_train
к новому набору данных X_test
.
Подумайте, что будет, если X_test
содержит разные уровни, чем X_train
для одной из его переменных. Например, скажемX_train["color"]
содержит только "red"
а также "green"
, но помимо этого, X_test["color"]
иногда содержит "blue"
.
Если мы используем pd.get_dummies
, X_test
закончится дополнительным "color_blue"
столбец, который X_train
нет, и несоответствие, вероятно, сломает наш код позже, особенно если мы будем кормить X_test
чтобы sklearn
модель, на которой мы обучались X_train
.
И если мы хотим обрабатывать данные таким образом в производственной среде, когда мы получаем по одному примеру за раз, pd.get_dummies
бесполезно.
С sklearn.OneHotEncoder
с другой стороны, как только мы создали кодировщик, мы можем повторно использовать его для получения одного и того же вывода каждый раз, со столбцами только для "red"
а также "green"
. И мы можем явно контролировать, что происходит, когда он выходит на новый уровень"blue"
: если мы думаем, что это невозможно, мы можем сказать ему, чтобы он выдал ошибку с handle_unknown="error"
; в противном случае мы можем сказать ему продолжить и просто установить красный и зеленый столбцы в 0, сhandle_unknown="ignore"
.
Мне очень нравится ответ Карла, и я поддержал его. Я просто немного расширю пример Карла, чтобы больше людей, надеюсь, оценили, что pd.get_dummies может обрабатывать неизвестные. Два приведенных ниже примера показывают, что pd.get_dummies может выполнять то же самое при обработке неизвестных файлов, как OHE .
# data is from @dzieciou's comment above
>>> data =pd.DataFrame(pd.Series(['good','bad','worst','good', 'good', 'bad']))
# new_data has two values that data does not have.
>>> new_data= pd.DataFrame(
pd.Series(['good','bad','worst','good', 'good', 'bad','excellent', 'perfect']))
Использование pd.get_dummies
>>> df = pd.get_dummies(data)
>>> col_list = df.columns.tolist()
>>> print(df)
0_bad 0_good 0_worst
0 0 1 0
1 1 0 0
2 0 0 1
3 0 1 0
4 0 1 0
5 1 0 0
6 0 0 0
7 0 0 0
>>> new_df = pd.get_dummies(new_data)
# handle unknow by using .reindex and .fillna()
>>> new_df = new_df.reindex(columns=col_list).fillna(0.00)
>>> print(new_df)
# 0_bad 0_good 0_worst
# 0 0 1 0
# 1 1 0 0
# 2 0 0 1
# 3 0 1 0
# 4 0 1 0
# 5 1 0 0
# 6 0 0 0
# 7 0 0 0
Использование OneHotEncoder
>>> encoder = OneHotEncoder(handle_unknown="ignore", sparse=False)
>>> encoder.fit(data)
>>> encoder.transform(new_data)
# array([[0., 1., 0.],
# [1., 0., 0.],
# [0., 0., 1.],
# [0., 1., 0.],
# [0., 1., 0.],
# [1., 0., 0.],
# [0., 0., 0.],
# [0., 0., 0.]])
Почему бы вам просто не кэшировать или не сохранять столбцы как переменную col_list из результирующих get_dummies, а затем использовать pd.reindex для выравнивания набора данных поезда и теста.... пример:
df = pd.get_dummies(data)
col_list = df.columns.tolist()
new_df = pd.get_dummies(new_data)
new_df = new_df.reindex(columns=col_list).fillna(0.00)
Этот вопрос был задан давно, но актуален и в 2023 году.
В одном предложении: Для задачи можно использовать оба, какой выбрать, зависит от личных предпочтений и других обстоятельств.
Немного подробнее:
И для OneHotEncoder, и для get_dummies это возможный и наиболее надежный способ явного указания категорий. Для OneHotEncoder этого можно добиться с помощью параметра «категории», который представляет собой список списков. Для get_dummies вам необходимо преобразовать соответствующие столбцы в категориальные с соответствующими категориями.
OneHotEncoder предполагает, что вы хотите закодировать все столбцы в ваших данных, поэтому, если это не так, вам придется либо вручную выбрать/преобразовать/объединить-с-исходными-столбцами, либо обернуть OneHotEncoder в преобразователь столбцов. Это намного проще, используя get_dummies.
Если вам нравится оставаться в пространстве DataFrame во время конвейера обработки данных, то pandas.get_dummies — самый прямой способ, но если вы полагаетесь на scikit Pipeline-s, то OneHotEncoder, завернутый в преобразователь столбцов, будет более простым.
Полное объяснение с примерами можно найти в моей статье о науке о данных.