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

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


当前回答

问题是传递给fit函数的数据(pd dataframe)的形状。 你必须通过1d列表。

其他回答

这是我解决你问题的办法。为了将包含文本的数据帧列转换为编码值,只需使用我的函数text_to_numbers,它返回LE的字典。Key是列LabelEncoder()作为值的列名。

def text_to_numbers(df):
        le_dict = dict()
        for i in df.columns:
            if df[i].dtype not in ["float64", "bool", "int64"]:
                le_dict[i] = preprocessing.LabelEncoder()
                df[i] = le_dict[i].fit_transform(df[i])
    
        return df, le_dict

下面的函数将使保留原始的未编码数据帧成为可能。

 def numbers_to_text(df, le_dict):
        for i in le_dict.keys():
            df[i] = le_dict[i].inverse_transform(df[i])
    
        return df

如果你拥有object类型的所有特征,那么上面写的第一个答案很好https://stackoverflow.com/a/31939145/5840973。

但是,假设我们有混合类型的列。然后,我们可以以编程方式获取类型对象类型名称的特征列表,然后对它们进行标签编码。

#Fetch features of type Object
objFeatures = dataframe.select_dtypes(include="object").columns

#Iterate a loop for features of type object
from sklearn import preprocessing
le = preprocessing.LabelEncoder()

for feat in objFeatures:
    dataframe[feat] = le.fit_transform(dataframe[feat].astype(str))
 

dataframe.info()

不,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

这是有可能做到这一切直接在熊猫,是非常适合的独特能力的替代方法。

首先,让我们创建一个字典的字典,将列及其值映射到新的替换值。

transform_dict = {}
for col in df.columns:
    cats = pd.Categorical(df[col]).categories
    d = {}
    for i, cat in enumerate(cats):
        d[cat] = i
    transform_dict[col] = d

transform_dict
{'location': {'New_York': 0, 'San_Diego': 1},
 'owner': {'Brick': 0, 'Champ': 1, 'Ron': 2, 'Veronica': 3},
 'pets': {'cat': 0, 'dog': 1, 'monkey': 2}}

由于这将始终是一个一对一的映射,我们可以反转内部字典以获得新值到原始值的映射。

inverse_transform_dict = {}
for col, d in transform_dict.items():
    inverse_transform_dict[col] = {v:k for k, v in d.items()}

inverse_transform_dict
{'location': {0: 'New_York', 1: 'San_Diego'},
 'owner': {0: 'Brick', 1: 'Champ', 2: 'Ron', 3: 'Veronica'},
 'pets': {0: 'cat', 1: 'dog', 2: 'monkey'}}

现在,我们可以使用replace方法的独特功能来获取一个嵌套的字典列表,并使用外部键作为列,使用内部键作为我们想要替换的值。

df.replace(transform_dict)
   location  owner  pets
0         1      1     0
1         0      2     1
2         0      0     0
3         1      1     2
4         1      3     1
5         0      2     1

通过再次链接replace方法,我们可以很容易地回到原来的方法

df.replace(transform_dict).replace(inverse_transform_dict)
    location     owner    pets
0  San_Diego     Champ     cat
1   New_York       Ron     dog
2   New_York     Brick     cat
3  San_Diego     Champ  monkey
4  San_Diego  Veronica     dog
5   New_York       Ron     dog