我试图使用scikit-learn的LabelEncoder来编码字符串标签的pandas DataFrame。由于数据帧有许多(50+)列,我想避免为每一列创建一个LabelEncoder对象;我宁愿只有一个大的LabelEncoder对象,它可以跨所有数据列工作。

将整个DataFrame扔到LabelEncoder中会产生以下错误。请记住,我在这里使用的是虚拟数据;实际上,我正在处理大约50列的字符串标记数据,所以需要一个解决方案,不引用任何列的名称。

import pandas
from sklearn import preprocessing 

df = pandas.DataFrame({
    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'], 
    'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'], 
    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego', 
                 'New_York']
})

le = preprocessing.LabelEncoder()

le.fit(df)

回溯(最近一次调用): 文件“”,第1行,在 文件"/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/预处理/label.py",第103行 y = column_or_1d(y, warn=True) 文件"/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py",第306行,在column_or_1d中 raise ValueError("错误的输入形状{0}".format(形状)) ValueError:错误的输入形状(6,3)

对于如何解决这个问题有什么想法吗?


当前回答

不,LabelEncoder不这样做。它接受类标签的1维数组并生成1维数组。它的设计目的是处理分类问题中的类标签,而不是任意数据,任何强迫它用于其他用途的尝试都需要代码将实际问题转换为它解决的问题(并将解决方案转换回原始空间)。

其他回答

我们可以使用scikit learn中的OrdinalEncoder来代替LabelEncoder,它允许多列编码。

将分类特征编码为整数数组。 这个转换器的输入应该是一个类似数组的整数或字符串,表示分类(离散)特征所取的值。特征被转换为序号整数。这将导致每个特性生成一列整数(0到n_categories - 1)。

>>> from sklearn.preprocessing import OrdinalEncoder
>>> enc = OrdinalEncoder()
>>> X = [['Male', 1], ['Female', 3], ['Female', 2]]
>>> enc.fit(X)
OrdinalEncoder()
>>> enc.categories_
[array(['Female', 'Male'], dtype=object), array([1, 2, 3], dtype=object)]
>>> enc.transform([['Female', 3], ['Male', 1]])
array([[0., 2.],
       [1., 0.]])

描述和示例都是从它的文档页面复制的,你可以在这里找到:

https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OrdinalEncoder.html#sklearn.preprocessing.OrdinalEncoder

主要使用@Alexander回答,但必须做一些更改-

cols_need_mapped = ['col1', 'col2']

mapper = {col: {cat: n for n, cat in enumerate(df[col].astype('category').cat.categories)} 
     for col in df[cols_need_mapped]}

for c in cols_need_mapped :
    df[c] = df[c].map(mapper[c])

然后,为了将来重用,你可以将输出保存到json文档中,当你需要它时,你可以读入并使用.map()函数,就像我上面所做的那样。

这是脚本

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
col_list = df.select_dtypes(include = "object").columns
for colsn in col_list:
    df[colsn] = le.fit_transform(df[colsn].astype(str))

从scikit-learn 0.20开始,你可以使用sklearn.compose.ColumnTransformer和sklearn.预处理. onehotencoder:

如果你只有分类变量,OneHotEncoder直接:

from sklearn.preprocessing import OneHotEncoder

OneHotEncoder(handle_unknown='ignore').fit_transform(df)

如果你有异构类型的特性:

from sklearn.compose import make_column_transformer
from sklearn.preprocessing import RobustScaler
from sklearn.preprocessing import OneHotEncoder

categorical_columns = ['pets', 'owner', 'location']
numerical_columns = ['age', 'weigth', 'height']
column_trans = make_column_transformer(
    (categorical_columns, OneHotEncoder(handle_unknown='ignore'),
    (numerical_columns, RobustScaler())
column_trans.fit_transform(df)

文档中有更多选项:http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogeneous-data

这并没有直接回答你的问题(Naputipulu Jon和PriceHardman对此有精彩的回答)

但是,对于一些分类任务等,您可以使用

pandas.get_dummies(input_df) 

这可以输入带有分类数据的数据框架,并返回带有二进制值的数据框架。变量值被编码到结果数据框架中的列名中。更多的