【问题标题】:How to perform OneHotEncoding in Sklearn, getting value error如何在 Sklearn 中执行 OneHotEncoding,获取值错误
【发布时间】:2018-05-27 05:09:23
【问题描述】:

我刚开始学习机器学习,在练习其中一项任务时,我遇到了值错误,但我遵循了与讲师相同的步骤。

我收到值错误,请帮助。

dff

     Country    Name
 0     AUS      Sri
 1     USA      Vignesh
 2     IND      Pechi
 3     USA      Raj

首先我执行了标签编码,

X=dff.values
label_encoder=LabelEncoder()
X[:,0]=label_encoder.fit_transform(X[:,0])

out:
X
array([[0, 'Sri'],
       [2, 'Vignesh'],
       [1, 'Pechi'],
       [2, 'Raj']], dtype=object)

然后对同一个 X 执行一次热编码

onehotencoder=OneHotEncoder( categorical_features=[0])
X=onehotencoder.fit_transform(X).toarray()

我收到以下错误:

ValueError                                Traceback (most recent call last)
<ipython-input-472-be8c3472db63> in <module>()
----> 1 X=onehotencoder.fit_transform(X).toarray()

C:\ProgramData\Anaconda3\lib\site-packages\sklearn\preprocessing\data.py in fit_transform(self, X, y)
   1900         """
   1901         return _transform_selected(X, self._fit_transform,
-> 1902                                    self.categorical_features, copy=True)
   1903 
   1904     def _transform(self, X):

C:\ProgramData\Anaconda3\lib\site-packages\sklearn\preprocessing\data.py in _transform_selected(X, transform, selected, copy)
   1695     X : array or sparse matrix, shape=(n_samples, n_features_new)
   1696     """
-> 1697     X = check_array(X, accept_sparse='csc', copy=copy, dtype=FLOAT_DTYPES)
   1698 
   1699     if isinstance(selected, six.string_types) and selected == "all":

C:\ProgramData\Anaconda3\lib\site-packages\sklearn\utils\validation.py in check_array(array, accept_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, warn_on_dtype, estimator)
    380                                       force_all_finite)
    381     else:
--> 382         array = np.array(array, dtype=dtype, order=order, copy=copy)
    383 
    384         if ensure_2d:

ValueError: could not convert string to float: 'Raj'

请编辑我的问题有什么问题,提前谢谢!

【问题讨论】:

  • 为什么不将'Name' 列更改为数字,就像对'Country' 所做的那样。 OneHotEncoder 只处理数字 X。所以要么在发送到 OneHotEncoder 之前从 X 中删除它,要么转换为数字。
  • 我只通过了一行X[:,0]=onehotencoder.fit_transform(X[:,0]).toarray(),但仍然是\sklearn\utils\validation.py:395: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and will raise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample. DeprecationWarning)
  • 是的,那是因为您将 rank1 数组,即 X[:,0] 传递给已弃用的 onehotencoder.fit_transform。因此,您需要通过 X[:,0].reshape(-1,1) 或使用 np.newaxis 来重塑它。
  • @AruneshSingh,谢谢,可以用我的数据发布您的答案吗?我尝试重塑并得到DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel(). y = column_or_1d(y, warn=True),我的输出是array([[1.0, 2], [2.0, 3], [1.0, 0], [2.0, 1]], dtype=object),应该是1还是0吧?
  • 这些只是警告,因此不会影响您的结果。

标签: python scikit-learn preprocessor sklearn-pandas one-hot-encoding


【解决方案1】:

您现在可以直接使用OneHotEncoding使用LabelEncoder,随着我们向 0.22 版迈进,许多人可能希望以这种方式来避免警告和潜在错误(请参阅 DOCSEXAMPLES)。


示例代码 1,其中所有列都被编码并且类别被明确指定:

import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

data= [["AUS", "Sri"],["USA","Vignesh"],["IND", "Pechi"],["USA","Raj"]]

df = pd.DataFrame(data, columns=['Country', 'Name'])
X = df.values

countries = np.unique(X[:,0])
names = np.unique(X[:,1])

ohe = OneHotEncoder(categories=[countries, names])
X = ohe.fit_transform(X).toarray()

print (X)

代码示例 1 的输出:

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

示例代码 2 显示用于指定类别的“自动”选项:

前 3 列编码国家名称,后 4 列编码个人姓名。

import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

data= [["AUS", "Sri"],["USA","Vignesh"],["IND", "Pechi"],["USA","Raj"]]

df = pd.DataFrame(data, columns=['Country', 'Name'])
X = df.values

ohe = OneHotEncoder(categories='auto')
X = ohe.fit_transform(X).toarray()

print (X)

代码示例 2 的输出(与 1 相同):

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

示例代码 3,其中只有第一列是一个热编码:

现在,这是独特的部分。如果您只需要对数据的特定列进行一次热编码怎么办?

注意:为了便于说明,我将最后一列保留为字符串。实际上,当最后一列已经是数字时,这样做更有意义)。

import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

data= [["AUS", "Sri"],["USA","Vignesh"],["IND", "Pechi"],["USA","Raj"]]

df = pd.DataFrame(data, columns=['Country', 'Name'])
X = df.values

countries = np.unique(X[:,0])
names = np.unique(X[:,1])

ohe = OneHotEncoder(categories=[countries]) # specify ONLY unique country names
tmp = ohe.fit_transform(X[:,0].reshape(-1, 1)).toarray()

X = np.append(tmp, names.reshape(-1,1), axis=1)

print (X)

代码示例 3 的输出:

[[1.0 0.0 0.0 'Pechi']
 [0.0 0.0 1.0 'Raj']
 [0.0 1.0 0.0 'Sri']
 [0.0 0.0 1.0 'Vignesh']]

【讨论】:

  • 从早上(过去几个小时)开始,我就一直被困在同一件事上。一直在试图找出类似于您上面的示例 3。您是如何理解这两行的。 tmp = ohe.fit_transform(X[:,0].reshape(-1, 1)).toarray() X = np.append(tmp, names.reshape(-1,1), axis=1) 我已经看了几遍scikit-learn的文档,还是不是很清楚。非常感谢您的回答
  • @michael,我刚刚在这里看到您的问题 - 抱歉。您需要 numpy 和 sklearn 的组合,但更多的是 numpy。如果这仍然没有帮助,请告诉我。
【解决方案2】:

下面的实现应该可以正常工作。注意onehotencoder的输入 fit_transform 不能是 1-rank 数组,输出也是稀疏的,我们使用 to_array() 来扩展它。

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder

data= [["AUS", "Sri"],["USA","Vignesh"],["IND", "Pechi"],["USA","Raj"]]


df = pd.DataFrame(data, columns=['Country', 'Name'])
X = df.values

le = LabelEncoder()
X_num = le.fit_transform(X[:,0]).reshape(-1,1)

ohe = OneHotEncoder()
X_num = ohe.fit_transform(X_num)

print (X_num.toarray())

X[:,0] = X_num

print (X)

【讨论】:

  • 它工作正常,如何以数据框格式显示 X?我
【解决方案3】:

如果您确实想对多个分类特征进行编码,另一种方法是使用带有 FeatureUnion 和几个自定义 Transformer 的 Pipeline。

首先需要两个转换器——一个用于选择单个列,一个用于使 LabelEncoder 在管道中可用(fit_transform 方法只需要 X,它需要一个可选的 y 才能在管道中工作)。

from sklearn.base import BaseEstimator, TransformerMixin

class SingleColumnSelector(TransformerMixin, BaseEstimator):
    def __init__(self, column):
        self.column = column

    def transform(self, X, y=None):
        return X[:, self.column].reshape(-1, 1)

    def fit(self, X, y=None):
        return self

class PipelineAwareLabelEncoder(TransformerMixin, BaseEstimator):
    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):
        return LabelEncoder().fit_transform(X).reshape(-1, 1)

接下来创建一个具有 2 个分支的管道(或只是一个 FeatureUnion) - 每个类别列一个。在每个 select 1 列中,对标签进行编码,然后进行一次热编码。

import pandas as pd
import numpy as np

from sklearn.preprocessing import LabelEncoder, OneHotEncoder, FunctionTransformer
from sklearn.pipeline import Pipeline, make_pipeline, FeatureUnion

pipeline = Pipeline([(
    'encoded_features',
    FeatureUnion([('countries',
        make_pipeline(
            SingleColumnSelector(0),
            PipelineAwareLabelEncoder(),
            OneHotEncoder()
        )), 
        ('names', make_pipeline(
            SingleColumnSelector(1),
            PipelineAwareLabelEncoder(),
            OneHotEncoder()
        ))
    ]))
])

最后通过管道运行您的完整数据帧 - 它将单独对每一列进行热编码并在最后连接。

df = pd.DataFrame([["AUS", "Sri"],["USA","Vignesh"],["IND", "Pechi"],["USA","Raj"]], columns=['Country', 'Name'])
X = df.values
transformed_X = pipeline.fit_transform(X)
print(transformed_X.toarray())

返回(前 3 列是国家,后 4 列是名称)

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

【讨论】:

    【解决方案4】:

    长话短说,如果您想使您的 df 变傻,请使用 dummy=pd.get_dummies 作为:

    dummy=pd.get_dummies(df['str'])
    df=pd.concat([df,dummy], axis=1)
    print(Data)
    

    【讨论】:

      猜你喜欢
      • 2017-07-01
      • 2020-06-30
      • 1970-01-01
      • 1970-01-01
      • 2020-04-11
      • 2016-02-19
      • 2021-11-24
      • 1970-01-01
      • 2019-02-12
      相关资源
      最近更新 更多