使用OneHotEncoder处理分类特征时出现问题

34

我希望对我数据集中的10个特征中的3个分类特征进行编码。我使用sklearn.preprocessing中的preprocessing来实现:

from sklearn import preprocessing
cat_features = ['color', 'director_name', 'actor_2_name']
enc = preprocessing.OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)

然而,由于出现了以下错误,我无法继续进行:

    array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: could not convert string to float: PG

我很惊讶为什么它会抱怨这个字符串,因为它应该将其转换!我有什么遗漏吗?

7个回答

51

如果你阅读 OneHotEncoder 的文档,你会看到 fit 的输入是 "Input array of type int"。因此,对于你的独热编码数据,你需要执行两个步骤。

from sklearn import preprocessing
cat_features = ['color', 'director_name', 'actor_2_name']
enc = preprocessing.LabelEncoder()
enc.fit(cat_features)
new_cat_features = enc.transform(cat_features)
print new_cat_features # [1 2 0]
new_cat_features = new_cat_features.reshape(-1, 1) # Needs to be the correct shape
ohe = preprocessing.OneHotEncoder(sparse=False) #Easier to read
print ohe.fit_transform(new_cat_features)

输出:

[[ 0.  1.  0.]
 [ 0.  0.  1.]
 [ 1.  0.  0.]]

编辑

0.20版本开始,这变得更加容易了,不仅因为OneHotEncoder现在可以很好地处理字符串,而且还因为我们可以使用ColumnTransformer轻松地转换多个列,下面是一个例子。

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
import numpy as np

X = np.array([['apple', 'red', 1, 'round', 0],
              ['orange', 'orange', 2, 'round', 0.1],
              ['bannana', 'yellow', 2, 'long', 0],
              ['apple', 'green', 1, 'round', 0.2]])
ct = ColumnTransformer(
    [('oh_enc', OneHotEncoder(sparse=False), [0, 1, 3]),],  # the column numbers I want to apply this to
    remainder='passthrough'  # This leaves the rest of my columns in place
)
print(ct2.fit_transform(X)) # Notice the output is a string

输出:

[['1.0' '0.0' '0.0' '0.0' '0.0' '1.0' '0.0' '0.0' '1.0' '1' '0']
 ['0.0' '0.0' '1.0' '0.0' '1.0' '0.0' '0.0' '0.0' '1.0' '2' '0.1']
 ['0.0' '1.0' '0.0' '0.0' '0.0' '0.0' '1.0' '1.0' '0.0' '2' '0']
 ['1.0' '0.0' '0.0' '1.0' '0.0' '0.0' '0.0' '0.0' '1.0' '1' '0.2']]

3
我完全不理解这个答案。您将编码器与数据集中的哪些数据配对?您能否提供更详细的示例,使用问题中的数据集进行说明? - Niakrais
1
你如何在管道中完成这个任务? - Dwagner
说实话,变量的命名很令人困惑。cat_features 不是数据集中分类特征的列表,而是具有一个分类列的数据集本身。LabelEncoder 一次只对一个分类变量进行编码。 - ShikharDua
关于EDIT:使用Pandas数据框架可以产生混合类型的输出。X = pd.DataFrame([['apple', 'red', 1, 'round', 0], ...ct = ColumnTransformer([('oh_enc', OneHotEncoder(sparse=False), [0, 1])], ...一起使用会产生混合输出:[[1.0 0.0 0.0 0.0 0.0 1.0 0.0 1 'round' 0.0]... - Sebastian Kropp

14
你可以使用LabelBinarizer类一次性地将文本类别转换为整数类别,然后再将整数类别转换为独热向量。
cat_features = ['color', 'director_name', 'actor_2_name']
encoder = LabelBinarizer()
new_cat_features = encoder.fit_transform(cat_features)
new_cat_features

请注意,默认情况下,这将返回一个密集的NumPy数组。您可以通过将sparse_output=True传递给LabelBinarizer构造函数来获取稀疏矩阵。
来源:使用Scikit-Learn和TensorFlow进行机器学习实战

7

如果数据集是以pandas数据框的形式存在,使用

pandas.get_dummies

会更加直接。

*已更正为pandas.get_dummies。


是的,这样做容易多了! - ShikharDua
使用 get_dummies,我仍在努力在不先合并测试集和训练集的情况下获得一致的独热编码。 - davideanastasia

5

来自文档:

categorical_features : “all” or array of indices or mask
Specify what features are treated as categorical.
‘all’ (default): All features are treated as categorical.
array of indices: Array of categorical feature indices.
mask: Array of length n_features and with dtype=bool.

pandas数据框的列名不起作用。如果您的分类特征是列号0、2和6,请使用以下代码:

from sklearn import preprocessing
cat_features = [0, 2, 6]
enc = preprocessing.OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)

需要注意的是,如果这些分类特征未进行标签编码,则在使用OneHotEncoder之前,您需要使用LabelEncoder对这些特征进行编码。


2

对@piman314的回答发表评论(没有足够的声望来发表评论)

这个问题只会出现在sklearn版本 <= 0.19中。 0.19文档 中的fit方法只允许整数输入:

fit(X, y = None)

X:类型为int的输入数组。

更新的版本 (0.20文档) 可以自动处理输入数据类型并允许字符串输入:

fit(X, y = None)

X:要确定每个特征类别的数据。


1

@Medo,

我遇到了相同的问题,感到非常沮丧。正如其他人所指出的,Scikit-Learn要求在考虑选择categorical_features参数提供的列之前,所有数据都必须是数字形式。

具体来说,列选择是由/sklearn/preprocessing/data.py中的_transform_selected()方法处理的,该方法的第一行是

X = check_array(X, accept_sparse='csc', copy=copy, dtype=FLOAT_DTYPES)

如果提供的数据框架X中的任何数据无法成功转换为浮点数,则此检查失败。

我认为sklearn.preprocessing.OneHotEncoder的文档在这方面非常误导。


0

如果像我一样,你对此感到沮丧,那么有一个简单的解决方法。只需使用Category Encoders' OneHotEncoder。这是一个Sklearn Contrib包,因此与scikit-learn API非常兼容。

这可以直接替换,并为您执行无聊的标签编码。

from category_encoders import OneHotEncoder
cat_features = ['color', 'director_name', 'actor_2_name']
enc = OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接