Get_Dummies (熊猫)和 OneHotEncoder (Scikit-learn)之间的优缺点是什么?

我正在学习不同的方法来将分类变量转换为机器学习分类器的数值。我遇到了 pd.get_dummies方法和 sklearn.preprocessing.OneHotEncoder(),我想看看它们在性能和使用方面有什么不同。

我找到了一个关于如何在 https://xgdgsc.wordpress.com/2015/03/20/note-on-using-onehotencoder-in-scikit-learn-to-work-on-categorical-features/上使用 OneHotEncoder()的教程,因为 sklearn文档对这个特性没有太大帮助。我感觉我做的不对... 但是

有人能解释一下在 sklearn.preprocessing.OneHotEncoder()pd.dummies之间使用 pd.dummies的利弊吗?我知道 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
70120 次浏览

OneHotEncoder不能直接处理字符串值。如果名义特性是字符串,那么首先需要将它们映射为整数。

pandas.get_dummies恰恰相反。默认情况下,它只将字符串列转换为单热表示,除非指定了列。

对于机器学习,几乎可以肯定要使用 sklearn.OneHotEncoder。对于其他任务,比如简单的分析,你可以使用 pd.get_dummies,这样更方便一些。

请注意,sklearn.OneHotEncoder在最新版本中已经更新,因此它对于分类变量和整数都是 接受附加条件

其关键在于 sklearn编码器创建了一个 依然存在可以 然后应用到新的数据集,使用相同的分类变量,具有一致的结果的函数。

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_dummiesX_test将最终与一个额外的 "color_blue"X_train没有,和不一致性可能会打破我们的代码后来,特别是如果我们正在供应 X_testsklearn模型,我们在 X_train培训。

如果我们想在生产环境中像这样处理数据,我们一次只接收一个示例,那么 pd.get_dummies就没有用了。

另一方面,使用 sklearn.OneHotEncoder,一旦我们创建了编码器,我们就可以重用它来每次产生相同的输出,只为 "red""green"创建列。我们可以明确地控制当它遇到新的级别 "blue"时会发生什么: 如果我们认为这是不可能的,那么我们可以告诉它使用 handle_unknown="error"抛出一个错误; 否则我们可以告诉它继续并简单地使用 handle_unknown="ignore"将红色和绿色列设置为0。

为什么不直接从结果 get _ Dummies 中将列缓存或保存为变量 col_ list,然后使用 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)

我真的很喜欢卡尔的回答,并且投了赞成票。我将稍微扩展一下 Carl 的例子,希望更多的人能够理解 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.]])