OneHotEncoder对分类功能的问题

时间:2017-04-24 12:56:01

标签: scikit-learn feature-extraction categorical-data

我想在我的数据集中的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 个答案:

答案 0 :(得分:36)

如果您阅读了OneHotEncoder的文档,您会看到fit的输入是"输入类型为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']]

答案 1 :(得分:13)

您可以应用两种转换(从文本类别到整数类别,然后从整数类别 使用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 = LabelBinarizer构造函数的True。

来源Hands-On Machine Learning with Scikit-Learn and TensorFlow

答案 2 :(得分:5)

如果数据集位于pandas数据框中,请使用

  

pandas.get_dummies

会更直截了当。

*从pandas.get_getdummies更正为pandas.get_dummies

答案 3 :(得分:3)

来自文档:

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 dataframe的列名不起作用。如果分类特征是列号0,2和6,则使用:

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

还必须注意,如果这些分类功能未经过标签编码,则在使用LabelEncoder

之前,您需要对这些功能使用OneHotEncoder

答案 4 :(得分: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的文档在这方面非常误导。

答案 5 :(得分:1)

评论@ piman314的答案(信誉不足以发表评论)

此问题仅在sklearn版本<= 0.19时发生。 Documentation of 0.19 for fit方法仅允许整数输入:

  

fit(X,y = None)

     

X:int类型的输入数组。

更高版本(documentation of 0.20)自动处理输入数据类型并允许字符串输入

  

fit(X,y = None)

     

X:用于确定每个功能类别的数据。

答案 6 :(得分:-1)

有一个简单的解决方法,如果您像我一样对此感到沮丧。只需使用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)