स्किकिट-लर्न में कई कॉलम में एन्कोडिंग लेबल करें


216

मैं स्ट्रिंग लेबल के LabelEncoderपांडा को एनकोड करने के लिए scikit-learn का उपयोग करने की कोशिश कर रहा हूं 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/preprocessing/babel.py", पंक्ति 103, फिट y में = column_or_1d (y, चेतावनी = सत्य) फ़ाइल "/User/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py", पंक्ति 306, column_or_1d बढ़ाएँ ValueError ("खराब इनपुट आकृति") 0} "। प्रारूप (आकार)) मान: खराब इनपुट आकार (6, 3)

कैसे इस समस्या के आसपास पाने के लिए पर कोई विचार?


आप ऐसा करने की कोशिश क्यों कर रहे हैं?
फ्रेड फू

dataframeस्ट्रिंग डेटा के एक बहु-स्तंभ एन्कोडिंग को सरल बनाने के लिए । मैं एन्कोडिंग ऑब्जेक्ट (ओं) को चित्रित कर रहा हूं, इसलिए 50 अलग-अलग वस्तुओं को अचार / अनपिकल करने से बचना चाहते हैं। इसके अलावा, मुझे आश्चर्य है कि अगर एनकोडर के पास डेटा को सरल बनाने का एक तरीका है, यानी प्रत्येक कॉलम में चर के प्रत्येक अद्वितीय संयोजन के लिए पहचानकर्ता के साथ एक पंक्ति को वापस करना।
ब्रायन

replaceविधि के लिए शब्दकोशों का एक शब्दकोश पारित करके पांडा में यह सब करने का एक सरल तरीका है । इस उत्तर को नीचे देखें
टेड पेट्रोउ

जवाबों:


451

आप इसे आसानी से कर सकते हैं,

df.apply(LabelEncoder().fit_transform)

EDIT2:

स्किटिट-लर्न 0.20 में, अनुशंसित तरीका है

OneHotEncoder().fit_transform(df)

OneHotEncoder के रूप में अब स्ट्रिंग इनपुट का समर्थन करता है। ColumnTransformer के साथ OneHotEncoder को केवल कुछ कॉलम पर लागू करना संभव है।

संपादित करें:

चूँकि यह उत्तर एक साल पहले का है, और कई अपवोट्स (एक इनाम सहित) उत्पन्न करता है, मुझे शायद इसे और आगे बढ़ाना चाहिए।

Inverse_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))

1
यह आश्चर्यजनक है, लेकिन इस मामले में हम व्युत्क्रम परिवर्तन कैसे लागू कर सकते हैं?
सुप्रेथ मीका

10
लेकिन अगर मैं इस समाधान का उपयोग पाइप लाइन में करना चाहता हूं, जैसे अलग फिट और ट्रांसफ़ॉर्म (ट्रेन पर फिट, और फिर परीक्षण-सेट पर उपयोग करें -> सीखे हुए शब्दकोश का फिर से उपयोग करें) क्या इसके साथ समर्थित है df.apply(LabelEncoder().fit_transform)?
जॉर्ज हेइलर

2
LabelBinarizerइसके बजाय इसके साथ काम करने और परीक्षण सेट के लिए शब्दकोश का फिर से उपयोग कैसे किया जा सकता है ? मैंने कोशिश की d = defaultdict(LabelBinarizer)और फिर fit = df.apply(lambda x: d[x.name].fit_transform(x))लेकिन एक अपवाद उठाया गया है Exception: Data must be 1-dimensional:। मुझे यकीन नहीं है कि मैं कैसे परिणामी DataFrame की तरह दिखने की उम्मीद करता हूं ... शायद प्रत्येक कॉलम को बिनाराइज्ड वैक्टर को पकड़ना चाहिए।
क़ुलु

4
अच्छा समाधान। केवल कुछ कॉलम में कैसे रूपांतरित करें?
स्टनलीवेट

1
अगर मैं एक कॉलम के लिए एनकोड जस्ट को उलटा करना चाहता हूं, तो मैं यह कैसे कर सकता हूं?
इब डी

95

जैसा कि लार्समैन ने उल्लेख किया है, लेबलइन्कोडर () केवल एक तर्क के रूप में 1-डी सरणी लेता है । उस ने कहा, अपने स्वयं के लेबल एनकोडर को रोल करना काफी आसान है जो आपके चुनने के कई स्तंभों पर काम करता है, और एक परिवर्तित डेटाफ़्रेम देता है। यहाँ मेरा कोड Zac स्टीवर्ट के उत्कृष्ट ब्लॉग पोस्ट के भाग में आधारित है जो यहाँ पाया गया है

एक कस्टम एनकोडर बनाना बस एक वर्ग बनाने होते हैं कि का जवाब fit(), transform()और fit_transform()तरीकों। आपके मामले में, एक अच्छी शुरुआत कुछ इस तरह हो सकती है:

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline

# Create some toy data in a Pandas dataframe
fruit_data = pd.DataFrame({
    'fruit':  ['apple','orange','pear','orange'],
    'color':  ['red','orange','green','green'],
    'weight': [5,6,3,4]
})

class MultiColumnLabelEncoder:
    def __init__(self,columns = None):
        self.columns = columns # array of column names to encode

    def fit(self,X,y=None):
        return self # not relevant here

    def transform(self,X):
        '''
        Transforms columns of X specified in self.columns using
        LabelEncoder(). If no columns specified, transforms all
        columns in X.
        '''
        output = X.copy()
        if self.columns is not None:
            for col in self.columns:
                output[col] = LabelEncoder().fit_transform(output[col])
        else:
            for colname,col in output.iteritems():
                output[colname] = LabelEncoder().fit_transform(col)
        return output

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

मान लीजिए कि हम संख्यात्मक विशेषता को छोड़ते हुए अपनी दो श्रेणीगत विशेषताओं ( fruitऔर color) को एनकोड करना चाहते weightहैं। हम इस प्रकार कर सकते हैं:

MultiColumnLabelEncoder(columns = ['fruit','color']).fit_transform(fruit_data)

जो हमारे fruit_dataडेटासेट से बदल देता है

यहां छवि विवरण दर्ज करें सेवा

यहां छवि विवरण दर्ज करें

इसे एक डेटाफ्रेम पास करना जिसमें पूरी तरह से श्रेणीबद्ध चर शामिल हैं और columnsपैरामीटर को छोड़ने से हर कॉलम को एन्कोड किया जाएगा (जो मुझे विश्वास है कि आप मूल रूप से क्या देख रहे थे):

MultiColumnLabelEncoder().fit_transform(fruit_data.drop('weight',axis=1))

यह रूपांतरित करता है

यहां छवि विवरण दर्ज करें सेवा

यहां छवि विवरण दर्ज करें

ध्यान दें कि यह संभवतः चोक हो जाएगा जब यह उन विशेषताओं को एनकोड करने की कोशिश करता है जो पहले से ही संख्यात्मक हैं (यदि आप चाहें तो इसे संभालने के लिए कुछ कोड जोड़ें)।

इसके बारे में एक और अच्छी बात यह है कि हम इस कस्टम ट्रांसफार्मर का उपयोग पाइप लाइन में कर सकते हैं:

encoding_pipeline = Pipeline([
    ('encoding',MultiColumnLabelEncoder(columns=['fruit','color']))
    # add more pipeline steps as needed
])
encoding_pipeline.fit_transform(fruit_data)

2
बस एहसास हुआ कि डेटा एक नारंगी रंग का हरे रंग का है। उफ़। ;)
मूल्यहार्डमैन

5
यह एक बार डेटा को बदलने का एक अच्छा तरीका है, लेकिन क्या होगा अगर मैं एक सत्यापन सेट पर इस परिवर्तन का पुन: उपयोग करना चाहता हूं। आपको फिर से fit_transform करना होगा और मुद्दे उठ सकते हैं जैसे कि मेरा नया डेटा सेट सभी श्रेणियों के लिए सभी श्रेणियों में नहीं है। उदाहरण के लिए, मेरे नए डेटा सेट में रंग हरा दिखाई नहीं देता है। इससे एन्कोडिंग गड़बड़ हो जाएगी।
बेन

3
@Ben से सहमत हैं। यह वास्तव में विधि के नामों से परे स्केलेर की नकल नहीं करता है। यदि आप इसे एक पाइपलाइन में डालने की कोशिश करते हैं, तो यह काम नहीं करेगा
Tgsmith61591

3
यह सुनिश्चित करने के लिए कि लेबल एन्कोडिंग ट्रेन और परीक्षण सेट दोनों के अनुरूप है, आप अपने संपूर्ण डेटासेट (ट्रेन + परीक्षण) पर एन्कोडिंग करना चाहते हैं। इससे पहले कि आप उन्हें ट्रेन और परीक्षण में विभाजित कर सकें, या आप उन्हें संयोजित कर सकते हैं, एन्कोडिंग प्रदर्शन कर सकते हैं, और उन्हें फिर से विभाजित कर सकते हैं।
प्राइसहर्डमैन

2
कैसे रिवर्स जा रहा है? डिकोडिंग मूल में वापस?
14:70 पर user702846

18

शिकंजे के बाद से 0.20 आप उपयोग कर सकते हैं sklearn.compose.ColumnTransformerऔरsklearn.preprocessing.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


inverse_transform()हालांकि ColumnTransformer पर समर्थित नहीं है। कम से कम, फिलहाल नहीं: github.com/scikit-learn/scikit-learn/issues/11463 । यह मेरे आवेदन के लिए एक बड़ा नुकसान है, और शायद दूसरों के लिए भी होगा।
Sander Vanden Hautte

16

हमें एक LabEncoder की आवश्यकता नहीं है।

आप कॉलम को श्रेणीबद्ध में बदल सकते हैं और फिर उनके कोड प्राप्त कर सकते हैं। मैंने इस प्रक्रिया को हर कॉलम पर लागू करने के लिए नीचे एक शब्दकोश समझ का उपयोग किया और परिणाम को समान सूचक और स्तंभ नामों के साथ समान आकृति के डेटाफ्रेम में वापस लपेट दिया।

>>> pd.DataFrame({col: df[col].astype('category').cat.codes for col in df}, index=df.index)
   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

एक मानचित्रण शब्दकोश बनाने के लिए, आप केवल एक शब्दकोश समझ का उपयोग करके श्रेणियों को गणना कर सकते हैं:

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

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

अगर मैं एक कॉलम के लिए वापस (रिवर्स) जाना चाहता हूं (उदाहरण लक्ष्य चर: Y) मैं इसे कैसे करूं?
इब डी

9

यह सीधे आपके प्रश्न का उत्तर नहीं देता है (जिसके लिए नेपुतिपुलु जॉन और प्राइसहार्डमैन के शानदार उत्तर हैं)

हालाँकि, कुछ वर्गीकरण कार्यों आदि के लिए आप उपयोग कर सकते हैं

pandas.get_dummies(input_df) 

यह श्रेणीबद्ध डेटा के साथ डेटाफ्रेम इनपुट कर सकता है और बाइनरी मानों के साथ डेटाफ्रेम लौटा सकता है। चर मान परिणाम डेटाफ़्रेम में स्तंभ नामों में एन्कोड किए गए हैं। अधिक


6

मान लें कि आप बस एक sklearn.preprocessing.LabelEncoder()वस्तु प्राप्त करने की कोशिश कर रहे हैं जिसका उपयोग आपके कॉलम को दर्शाने के लिए किया जा सकता है, आपको बस इतना करना है:

le.fit(df.columns)

उपरोक्त कोड में आपके पास प्रत्येक कॉलम के अनुरूप एक अद्वितीय संख्या होगी। अधिक सटीक रूप से, आपके पास 1: 1 की मैपिंग df.columnsहोगी le.transform(df.columns.get_values())। कॉलम की एन्कोडिंग प्राप्त करने के लिए, बस इसे पास करें le.transform(...)। एक उदाहरण के रूप में, निम्नलिखित प्रत्येक कॉलम के लिए एन्कोडिंग प्राप्त करेगा:

le.transform(df.columns.get_values())

मान लें कि आप sklearn.preprocessing.LabelEncoder()अपनी सभी पंक्ति लेबलों के लिए एक ऑब्जेक्ट बनाना चाहते हैं, जो आप निम्न कार्य कर सकते हैं:

le.fit([y for x in df.get_values() for y in x])

इस मामले में, आपके पास गैर-अद्वितीय पंक्ति लेबल होने की संभावना है (जैसा कि आपके प्रश्न में दिखाया गया है)। यह देखने के लिए कि आप जो एनकोडर बनाए गए हैं, वे किस वर्ग के हैं le.classes_। आप ध्यान देंगे कि इसमें समान तत्व होने चाहिए set(y for x in df.get_values() for y in x)। एक बार फिर एक पंक्ति लेबल को एन्कोडेड लेबल उपयोग में बदलने के लिए le.transform(...)। एक उदाहरण के रूप में, यदि आप df.columnsसरणी में पहली कॉलम और पहली पंक्ति के लिए लेबल पुनः प्राप्त करना चाहते हैं, तो आप ऐसा कर सकते हैं:

le.transform([df.get_value(0, df.columns[0])])

आपकी टिप्पणी में जो प्रश्न था वह थोड़ा अधिक जटिल है, लेकिन फिर भी पूरा किया जा सकता है:

le.fit([str(z) for z in set((x[0], y) for x in df.iteritems() for y in x[1])])

उपरोक्त कोड निम्न कार्य करता है:

  1. (कॉलम, पंक्ति) के सभी जोड़ों का एक अनूठा संयोजन बनाएं
  2. प्रत्येक जोड़ी को टुपल के स्ट्रिंग संस्करण के रूप में प्रस्तुत करता है। इस पर काबू पाने के लिए एक समाधान हैLabelEncoder क्लास नाम के रूप में ट्यूपल्स का समर्थन नहीं वर्ग ।
  3. करने के लिए नए आइटम फिट बैठता है LabelEncoder

अब इस नए मॉडल का उपयोग करने के लिए यह थोड़ा अधिक जटिल है। यह मानते हुए कि हम पिछले उदाहरण (df.columns में पहला कॉलम और पहली पंक्ति में) उसी आइटम के लिए प्रतिनिधित्व निकालना चाहते हैं, हम यह कर सकते हैं:

le.transform([str((df.columns[0], df.get_value(0, df.columns[0])))])

याद रखें कि प्रत्येक लुकअप अब एक टपल का एक स्ट्रिंग प्रतिनिधित्व है जिसमें कॉलम (स्तंभ, पंक्ति) शामिल है।


5

नहीं, LabelEncoderऐसा नहीं करता। यह क्लास लेबल के 1-डी सरणियों को लेता है और 1-डी सरणियों का उत्पादन करता है। इसे वर्गीकरण की समस्याओं में वर्ग लेबल को संभालने के लिए डिज़ाइन किया गया है, मनमाना डेटा नहीं है, और इसे अन्य उपयोगों में बाध्य करने के किसी भी प्रयास को वास्तविक समस्या को हल करने के लिए कोड की आवश्यकता होगी (और मूल स्थान पर समाधान)।


ठीक है, यह देखते हुए, आपके सुझाव का सबसे अच्छा तरीका क्या है कि मैं DataFrameएक समय में एक पूरे द्वारा स्ट्रिंग लेबल को एन्कोड कर सकता हूं ?
ब्रायन

@ ब्रायन LabelEncoderकोड को देखें और इसे अनुकूलित करें। मैं स्वयं पंडों का उपयोग नहीं करता, इसलिए मुझे नहीं पता कि यह कितना कठिन होगा।
फ्रेड फू

मैं अन्य pandasलोगों को भी इस सवाल पर एक दरार लेने देता हूं - मुझे यकीन है कि मैं इस चुनौती वाला एकमात्र व्यक्ति नहीं हूं, इसलिए मुझे आशा है कि वहां एक पूर्व निर्मित समाधान हो सकता है।
ब्रायन

5

यह तथ्य के बाद एक-डेढ़ साल का है, लेकिन मुझे भी, .transform()एक बार में कई पांडा डेटाफ्रेम कॉलम (और .inverse_transform()साथ ही साथ सक्षम होना चाहिए) में सक्षम होना चाहिए । यह ऊपर @PriceHardman के उत्कृष्ट सुझाव पर फैलता है:

class MultiColumnLabelEncoder(LabelEncoder):
    """
    Wraps sklearn LabelEncoder functionality for use on multiple columns of a
    pandas dataframe.

    """
    def __init__(self, columns=None):
        self.columns = columns

    def fit(self, dframe):
        """
        Fit label encoder to pandas columns.

        Access individual column classes via indexig `self.all_classes_`

        Access individual column encoders via indexing
        `self.all_encoders_`
        """
        # if columns are provided, iterate through and get `classes_`
        if self.columns is not None:
            # ndarray to hold LabelEncoder().classes_ for each
            # column; should match the shape of specified `columns`
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            self.all_encoders_ = np.ndarray(shape=self.columns.shape,
                                            dtype=object)
            for idx, column in enumerate(self.columns):
                # fit LabelEncoder to get `classes_` for the column
                le = LabelEncoder()
                le.fit(dframe.loc[:, column].values)
                # append the `classes_` to our ndarray container
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                # append this column's encoder
                self.all_encoders_[idx] = le
        else:
            # no columns specified; assume all are to be encoded
            self.columns = dframe.iloc[:, :].columns
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            for idx, column in enumerate(self.columns):
                le = LabelEncoder()
                le.fit(dframe.loc[:, column].values)
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                self.all_encoders_[idx] = le
        return self

    def fit_transform(self, dframe):
        """
        Fit label encoder and return encoded labels.

        Access individual column classes via indexing
        `self.all_classes_`

        Access individual column encoders via indexing
        `self.all_encoders_`

        Access individual column encoded labels via indexing
        `self.all_labels_`
        """
        # if columns are provided, iterate through and get `classes_`
        if self.columns is not None:
            # ndarray to hold LabelEncoder().classes_ for each
            # column; should match the shape of specified `columns`
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            self.all_encoders_ = np.ndarray(shape=self.columns.shape,
                                            dtype=object)
            self.all_labels_ = np.ndarray(shape=self.columns.shape,
                                          dtype=object)
            for idx, column in enumerate(self.columns):
                # instantiate LabelEncoder
                le = LabelEncoder()
                # fit and transform labels in the column
                dframe.loc[:, column] =\
                    le.fit_transform(dframe.loc[:, column].values)
                # append the `classes_` to our ndarray container
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                self.all_encoders_[idx] = le
                self.all_labels_[idx] = le
        else:
            # no columns specified; assume all are to be encoded
            self.columns = dframe.iloc[:, :].columns
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            for idx, column in enumerate(self.columns):
                le = LabelEncoder()
                dframe.loc[:, column] = le.fit_transform(
                        dframe.loc[:, column].values)
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                self.all_encoders_[idx] = le
        return dframe.loc[:, self.columns].values

    def transform(self, dframe):
        """
        Transform labels to normalized encoding.
        """
        if self.columns is not None:
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[
                    idx].transform(dframe.loc[:, column].values)
        else:
            self.columns = dframe.iloc[:, :].columns
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[idx]\
                    .transform(dframe.loc[:, column].values)
        return dframe.loc[:, self.columns].values

    def inverse_transform(self, dframe):
        """
        Transform labels back to original encoding.
        """
        if self.columns is not None:
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[idx]\
                    .inverse_transform(dframe.loc[:, column].values)
        else:
            self.columns = dframe.iloc[:, :].columns
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[idx]\
                    .inverse_transform(dframe.loc[:, column].values)
        return dframe.loc[:, self.columns].values

उदाहरण:

अगर dfऔर df_copy()मिश्रित प्रकार के pandasडेटाफ्रेम हैं, तो आप कॉलम को निम्नलिखित तरीके MultiColumnLabelEncoder()से लागू कर सकते हैं dtype=object:

# get `object` columns
df_object_columns = df.iloc[:, :].select_dtypes(include=['object']).columns
df_copy_object_columns = df_copy.iloc[:, :].select_dtypes(include=['object']).columns

# instantiate `MultiColumnLabelEncoder`
mcle = MultiColumnLabelEncoder(columns=object_columns)

# fit to `df` data
mcle.fit(df)

# transform the `df` data
mcle.transform(df)

# returns output like below
array([[1, 0, 0, ..., 1, 1, 0],
       [0, 5, 1, ..., 1, 1, 2],
       [1, 1, 1, ..., 1, 1, 2],
       ..., 
       [3, 5, 1, ..., 1, 1, 2],

# transform `df_copy` data
mcle.transform(df_copy)

# returns output like below (assuming the respective columns 
# of `df_copy` contain the same unique values as that particular 
# column in `df`
array([[1, 0, 0, ..., 1, 1, 0],
       [0, 5, 1, ..., 1, 1, 2],
       [1, 1, 1, ..., 1, 1, 2],
       ..., 
       [3, 5, 1, ..., 1, 1, 2],

# inverse `df` data
mcle.inverse_transform(df)

# outputs data like below
array([['August', 'Friday', '2013', ..., 'N', 'N', 'CA'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['August', 'Monday', '2014', ..., 'N', 'N', 'NJ'],
       ..., 
       ['February', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['March', 'Tuesday', '2013', ..., 'N', 'N', 'NJ']], dtype=object)

# inverse `df_copy` data
mcle.inverse_transform(df_copy)

# outputs data like below
array([['August', 'Friday', '2013', ..., 'N', 'N', 'CA'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['August', 'Monday', '2014', ..., 'N', 'N', 'NJ'],
       ..., 
       ['February', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['March', 'Tuesday', '2013', ..., 'N', 'N', 'NJ']], dtype=object)

आप इंडेक्सिंग के माध्यम से प्रत्येक कॉलम को फिट करने के लिए व्यक्तिगत कॉलम क्लासेस, कॉलम लेबल और कॉलम एनकोडर का उपयोग कर सकते हैं:

mcle.all_classes_
mcle.all_encoders_
mcle.all_labels_


हाय जेसन, mcle.all_labels_ काम करने के लिए प्रकट नहीं होता है (पायथन 3.5, कॉनडा 4.3.29, स्केलेर 0.18.1, पंडास 0.20.1। मुझे प्राप्त होता है: विशेषता: 'MultiColumniabelEncoder' ऑब्जेक्ट में कोई विशेषता नहीं है 'all_labels_'
जेसन

@ जेसन हाय, क्षमा करें, मैंने इसे आज तक नहीं देखा: / लेकिन अगर मुझे अनुमान लगाना था, तो मैं कहूंगा कि आपने अभी fitऊपर की विधि का उपयोग किया है जो वास्तव में तब तक कोई लेबल नहीं लगाएगा जब तक आप इसे लागू नहीं करते ( transform/ fit_transform) आँकड़े।
जेसन वोलोसोनोविच

मुझे लगता है कि आपको एक बेहतर उदाहरण देने की आवश्यकता है - मैं आपके सभी कोड फिर से नहीं ला सकता।
user702846

2

@PriceHardman के समाधान पर उठाए गए टिप्पणियों के बाद मैं कक्षा के निम्नलिखित संस्करण का प्रस्ताव करूंगा:

class LabelEncodingColoumns(BaseEstimator, TransformerMixin):
def __init__(self, cols=None):
    pdu._is_cols_input_valid(cols)
    self.cols = cols
    self.les = {col: LabelEncoder() for col in cols}
    self._is_fitted = False

def transform(self, df, **transform_params):
    """
    Scaling ``cols`` of ``df`` using the fitting

    Parameters
    ----------
    df : DataFrame
        DataFrame to be preprocessed
    """
    if not self._is_fitted:
        raise NotFittedError("Fitting was not preformed")
    pdu._is_cols_subset_of_df_cols(self.cols, df)

    df = df.copy()

    label_enc_dict = {}
    for col in self.cols:
        label_enc_dict[col] = self.les[col].transform(df[col])

    labelenc_cols = pd.DataFrame(label_enc_dict,
        # The index of the resulting DataFrame should be assigned and
        # equal to the one of the original DataFrame. Otherwise, upon
        # concatenation NaNs will be introduced.
        index=df.index
    )

    for col in self.cols:
        df[col] = labelenc_cols[col]
    return df

def fit(self, df, y=None, **fit_params):
    """
    Fitting the preprocessing

    Parameters
    ----------
    df : DataFrame
        Data to use for fitting.
        In many cases, should be ``X_train``.
    """
    pdu._is_cols_subset_of_df_cols(self.cols, df)
    for col in self.cols:
        self.les[col].fit(df[col])
    self._is_fitted = True
    return self

यह वर्ग प्रशिक्षण सेट पर एनकोडर को फिट करता है और रूपांतरण करते समय फिट संस्करण का उपयोग करता है। कोड का प्रारंभिक संस्करण यहां पाया जा सकता है


2

एक के LabelEncoder()साथ कई स्तंभों के लिए एक छोटा रास्ता dict():

from sklearn.preprocessing import LabelEncoder
le_dict = {col: LabelEncoder() for col in columns }
for col in columns:
    le_dict[col].fit_transform(df[col])

और आप le_dictकिसी अन्य कॉलम को लेबल करने के लिए इसका उपयोग कर सकते हैं :

le_dict[col].transform(df_another[col])

2

यह सब सीधे पंडों में करना संभव है और यह एक अद्वितीय क्षमता के लिए अच्छी तरह से अनुकूल है replace विधि ।

सबसे पहले, हम अपने नए प्रतिस्थापन मूल्यों के लिए स्तंभों और उनके मूल्यों का मानचित्रण शब्दकोश बनाते हैं।

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

2

यहाँ और कुछ उत्तरों के साथ बहुत सी खोज और प्रयोग के बाद, मुझे लगता है कि आपका उत्तर यहाँ है :

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

2

मैंने लेबलइंकोडर के स्रोत कोड ( https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/preprocessing/label.py ) की जाँच की। यह संख्यात्मक परिवर्तन के एक सेट पर आधारित था, जिसमें से एक np.unique () है। और यह फ़ंक्शन केवल 1-डी सरणी इनपुट लेता है। (अगर मैं ग़लत हूं तो मेरी गलती सुझाएं)।

बहुत कठिन विचार ... सबसे पहले, पहचानें कि कौन से कॉलम में लेबलइंकोडर की जरूरत है, फिर प्रत्येक कॉलम के माध्यम से लूप करें।

def cat_var(df): 
    """Identify categorical features. 

    Parameters
    ----------
    df: original df after missing operations 

    Returns
    -------
    cat_var_df: summary df with col index and col name for all categorical vars
    """
    col_type = df.dtypes
    col_names = list(df)

    cat_var_index = [i for i, x in enumerate(col_type) if x=='object']
    cat_var_name = [x for i, x in enumerate(col_names) if i in cat_var_index]

    cat_var_df = pd.DataFrame({'cat_ind': cat_var_index, 
                               'cat_name': cat_var_name})

    return cat_var_df



from sklearn.preprocessing import LabelEncoder 

def column_encoder(df, cat_var_list):
    """Encoding categorical feature in the dataframe

    Parameters
    ----------
    df: input dataframe 
    cat_var_list: categorical feature index and name, from cat_var function

    Return
    ------
    df: new dataframe where categorical features are encoded
    label_list: classes_ attribute for all encoded features 
    """

    label_list = []
    cat_var_df = cat_var(df)
    cat_list = cat_var_df.loc[:, 'cat_name']

    for index, cat_feature in enumerate(cat_list): 

        le = LabelEncoder()

        le.fit(df.loc[:, cat_feature])    
        label_list.append(list(le.classes_))

        df.loc[:, cat_feature] = le.transform(df.loc[:, cat_feature])

    return df, label_list

एन्कोडिंग के बाद दिया गया df एक होगा और लेबल_लिस्ट आपको दिखाएगा कि संबंधित कॉलम में उन सभी मूल्यों का क्या अर्थ है। यह एक डेटा प्रक्रिया स्क्रिप्ट से स्निपेट है जिसे मैंने काम के लिए लिखा था। मुझे लगता है कि अगर आपको लगता है कि कोई और सुधार हो सकता है।

संपादित करें: बस यहां उल्लेख करना चाहते हैं कि ऊपर दिए गए तरीके डेटा फ्रेम के साथ काम करते हैं जिसमें कोई सबसे अच्छा गायब नहीं है। यह निश्चित नहीं है कि यह डेटा फ़्रेम की ओर कैसे काम कर रहा है, इसमें लापता डेटा है। (मैं तरीकों से ऊपर निष्पादित करने से पहले लापता प्रक्रिया के साथ एक सौदा था)


1

यदि हमारे पास लेबल एन्कोडिंग करने के लिए एकल कॉलम है और इसका उलटा इसका आसान रूप बदल देता है तो यह कैसे करें जब अजगर में कई कॉलम हों

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

1

यदि आपके पास डेटाफ्रेम में संख्यात्मक और श्रेणीबद्ध दोनों प्रकार के डेटा हैं, तो आप इसका उपयोग कर सकते हैं: यहाँ एक्स मेरे डेटाफ़्रेम में श्रेणीबद्ध और संख्यात्मक दोनों चर हैं

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]])

नोट: यदि आप उन्हें वापस बदलने में रुचि नहीं रखते हैं तो यह तकनीक अच्छी है।


1

न्यूरक्सल का उपयोग करना

TLDR; आप यहाँ का उपयोग कर सकते FlattenForEach बस की तरह अपने df को बदलने के लिए वर्ग आवरण: FlattenForEach(LabelEncoder(), then_unflatten=True).fit_transform(df)

इस पद्धति के साथ, आपका लेबल एनकोडर एक नियमित स्कोरिट-लर्न पाइपलाइन के भीतर फिट और बदलने में सक्षम होगा । चलो बस आयात करते हैं:

from sklearn.preprocessing import LabelEncoder
from neuraxle.steps.column_transformer import ColumnTransformer
from neuraxle.steps.loop import FlattenForEach

कॉलम के लिए एक ही सांकेतिक एनकोडर:

यहाँ बताया गया है कि कैसे एक सांकेतिक लेबलइन्कोडर को एनकोड करने के लिए सभी डेटा पर लागू किया जाएगा:

    p = FlattenForEach(LabelEncoder(), then_unflatten=True)

परिणाम:

    p, predicted_output = p.fit_transform(df.values)
    expected_output = np.array([
        [6, 7, 6, 8, 7, 7],
        [1, 3, 0, 1, 5, 3],
        [4, 2, 2, 4, 4, 2]
    ]).transpose()
    assert np.array_equal(predicted_output, expected_output)

प्रति कॉलम विभिन्न एनकोडर:

और यहां बताया गया है कि पालतू जानवरों पर पहला स्टैंडअलोन लेबलएन्कोडर कैसे लगाया जाएगा, और कॉलम मालिक और स्थान के लिए एक दूसरा साझा किया जाएगा। तो सटीक होने के लिए, हमारे यहां अलग-अलग और साझा लेबल एनकोडर का मिश्रण है:

    p = ColumnTransformer([
        # A different encoder will be used for column 0 with name "pets":
        (0, FlattenForEach(LabelEncoder(), then_unflatten=True)),
        # A shared encoder will be used for column 1 and 2, "owner" and "location":
        ([1, 2], FlattenForEach(LabelEncoder(), then_unflatten=True)),
    ], n_dimension=2)

परिणाम:

    p, predicted_output = p.fit_transform(df.values)
    expected_output = np.array([
        [0, 1, 0, 2, 1, 1],
        [1, 3, 0, 1, 5, 3],
        [4, 2, 2, 4, 4, 2]
    ]).transpose()
    assert np.array_equal(predicted_output, expected_output)

0

मुख्य रूप से @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()फ़ंक्शन का उपयोग करते हैं जैसे मैंने ऊपर किया था।


0

समस्या डेटा (पीडी डेटाफ़्रेम) के आकार की है जो आप फिट कार्य कर रहे हैं। आपको 1d सूची पास करनी है।


0
import pandas as pd
from sklearn.preprocessing import LabelEncoder

train=pd.read_csv('.../train.csv')

#X=train.loc[:,['waterpoint_type_group','status','waterpoint_type','source_class']].values
# Create a label encoder object 
def MultiLabelEncoder(columnlist,dataframe):
    for i in columnlist:

        labelencoder_X=LabelEncoder()
        dataframe[i]=labelencoder_X.fit_transform(dataframe[i])
columnlist=['waterpoint_type_group','status','waterpoint_type','source_class','source_type']
MultiLabelEncoder(columnlist,train)

यहां मैं स्थान से एक सीएसवी पढ़ रहा हूं और फ़ंक्शन में मैं उस कॉलम सूची को पास कर रहा हूं जिसे मैं लेबलकोड करना चाहता हूं और वह डेटाफ्रेम जो मैं इसे लागू करना चाहता हूं।


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')

यह सबसे कुशल नहीं है, हालांकि यह काम करता है और यह सुपर सरल है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.