我试图使用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)

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


当前回答

你可以很容易地做到,

df.apply(LabelEncoder().fit_transform)

EDIT2:

在scikit-learn 0.20中,推荐的方法是

OneHotEncoder().fit_transform(df)

因为OneHotEncoder现在支持字符串输入。 使用ColumnTransformer可以只对某些列应用OneHotEncoder。

编辑:

由于这个最初的答案是一年多前的,并获得了许多赞(包括赏金),我可能应该进一步扩展它。

对于inverse_transform和transform,你需要做一点修改。

from collections import defaultdict
d = defaultdict(LabelEncoder)

这样,您现在将所有列LabelEncoder保留为字典。

# Encoding the variable
fit = df.apply(lambda x: d[x.name].fit_transform(x))

# Inverse the encoded
fit.apply(lambda x: d[x.name].inverse_transform(x))

# Using the dictionary to label future data
df.apply(lambda x: d[x.name].transform(x))

MOAR编辑:

使用Neuraxle的flatforeach步骤,也可以在一次对所有平坦数据使用相同的LabelEncoder:

FlattenForEach(LabelEncoder(), then_unflatten=True).fit_transform(df)

要根据数据列使用单独的LabelEncoders,或者如果只有一些数据列需要进行标签编码,而不需要其他数据列,那么使用ColumnTransformer是一种解决方案,它允许对列选择和LabelEncoder实例进行更多控制。

其他回答

如果你在数据框架中有数值和类别两种类型的数据 你可以使用:这里X是我的数据框架,有分类变量和数值变量

from sklearn import preprocessing
le = preprocessing.LabelEncoder()

for i in range(0,X.shape[1]):
    if X.dtypes[i]=='object':
        X[X.columns[i]] = le.fit_transform(X[X.columns[i]])

注意:如果你对转换它们不感兴趣,这个技巧是很好的。

在这里和其他地方进行了大量的搜索和实验后,我认为你的答案是:

pd.DataFrame(列= df.columns, data = LabelEncoder () .fit_transform (df.values.flatten ()) .reshape (df.shape))

这将跨列保留类别名称:

import pandas as pd
from sklearn.preprocessing import LabelEncoder

df = pd.DataFrame([['A','B','C','D','E','F','G','I','K','H'],
                   ['A','E','H','F','G','I','K','','',''],
                   ['A','C','I','F','H','G','','','','']], 
                  columns=['A1', 'A2', 'A3','A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10'])

pd.DataFrame(columns=df.columns, data=LabelEncoder().fit_transform(df.values.flatten()).reshape(df.shape))

    A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
0   1   2   3   4   5   6   7   9   10  8
1   1   5   8   6   7   9   10  0   0   0
2   1   3   9   6   8   7   0   0   0   0

下面是我一次性转换多列的解决方案,以及精确的inverse_transform

from sklearn import preprocessing
columns = ['buying','maint','lug_boot','safety','cls']  # columns names where transform is required
for X in columns:
  exec(f'le_{X} = preprocessing.LabelEncoder()')  #create label encoder with name "le_X", where X is column name
  exec(f'df.{X} = le_{X}.fit_transform(df.{X})')  #execute fit transform for column X with respective lable encoder "le_X", where X is column name
df.head()  # to display transformed results

for X in columns:
  exec(f'df.{X} = le_{X}.inverse_transform(df.{X})')  #execute inverse_transform for column X with respective lable encoder "le_X", where X is column name
df.head() # to display Inverse transformed results of df

你可以很容易地做到,

df.apply(LabelEncoder().fit_transform)

EDIT2:

在scikit-learn 0.20中,推荐的方法是

OneHotEncoder().fit_transform(df)

因为OneHotEncoder现在支持字符串输入。 使用ColumnTransformer可以只对某些列应用OneHotEncoder。

编辑:

由于这个最初的答案是一年多前的,并获得了许多赞(包括赏金),我可能应该进一步扩展它。

对于inverse_transform和transform,你需要做一点修改。

from collections import defaultdict
d = defaultdict(LabelEncoder)

这样,您现在将所有列LabelEncoder保留为字典。

# Encoding the variable
fit = df.apply(lambda x: d[x.name].fit_transform(x))

# Inverse the encoded
fit.apply(lambda x: d[x.name].inverse_transform(x))

# Using the dictionary to label future data
df.apply(lambda x: d[x.name].transform(x))

MOAR编辑:

使用Neuraxle的flatforeach步骤,也可以在一次对所有平坦数据使用相同的LabelEncoder:

FlattenForEach(LabelEncoder(), then_unflatten=True).fit_transform(df)

要根据数据列使用单独的LabelEncoders,或者如果只有一些数据列需要进行标签编码,而不需要其他数据列,那么使用ColumnTransformer是一种解决方案,它允许对列选择和LabelEncoder实例进行更多控制。

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