在Scikit-learn中跨多列进行标签编码

323

我正在尝试使用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)

Traceback (most recent call last): File "", line 1, in File "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py", line 103, in fit y = column_or_1d(y, warn=True) File "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py", line 306, in column_or_1d raise ValueError("bad input shape {0}".format(shape)) ValueError: bad input shape (6, 3)

您有什么想法可以解决这个问题吗?


为了简化对包含字符串数据的多列dataframe进行编码,我正在选择编码对象,因此希望避免对50个独立对象进行pickle/unpickle操作。另外,我想知道是否有一种方法可以让编码器简化数据,例如只返回每列中变量的唯一组合的一个标识符所在的行。 - Bryan
可以通过将一个字典的字典传递给 replace 方法,在 pandas 中以简单的方式完成所有操作。请参见下面的答案 - Ted Petrou
1
scikit-learn 0.20 开始,不需要实现自定义类来对多列进行标签编码。您可以直接使用OrdinalEncoder - Ric S
25个回答

1
如果我们只有一个列需要进行标签编码并且进行其反向转换,那么在Python中该如何操作是很简单的。但当有多个列时,应该如何处理呢?
def stringtocategory(dataset):
    '''
    @author puja.sharma
    @see The function label encodes the object type columns and gives label      encoded and inverse tranform of the label encoded data
    @param dataset dataframe on whoes column the label encoding has to be done
    @return label encoded and inverse tranform of the label encoded data.
   ''' 
   data_original = dataset[:]
   data_tranformed = dataset[:]
   for y in dataset.columns:
       #check the dtype of the column object type contains strings or chars
       if (dataset[y].dtype == object):
          print("The string type features are  : " + y)
          le = preprocessing.LabelEncoder()
          le.fit(dataset[y].unique())
          #label encoded data
          data_tranformed[y] = le.transform(dataset[y])
          #inverse label transform  data
          data_original[y] = le.inverse_transform(data_tranformed[y])
   return data_tranformed,data_original

0

这是我一次性转换多列的解决方案,同时提供准确的反向转换。

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

0
这是我的解决方案,针对您的问题。为了将包含文本的数据框列转换为编码值,只需使用我的函数text_to_numbers,它返回一个LE字典。键是该列名称,该列的值为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

0
问题在于您传递给fit函数的数据形状(pd dataframe)。 您必须传递1d列表。

0

这个怎么样?

def MultiColumnLabelEncode(choice, columns, X):
    LabelEncoders = []
    if choice == 'encode':
        for i in enumerate(columns):
            LabelEncoders.append(LabelEncoder())
        i=0    
        for cols in columns:
            X[:, cols] = LabelEncoders[i].fit_transform(X[:, cols])
            i += 1
    elif choice == 'decode': 
        for cols in columns:
            X[:, cols] = LabelEncoders[i].inverse_transform(X[:, cols])
            i += 1
    else:
        print('Please select correct parameter "choice". Available parameters: encode/decode')

虽然它不是最高效的,但它能够正常工作且非常简单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接