web-dev-qa-db-de.com

Beschriftungscodierung über mehrere Spalten hinweg in Scikit-Learn

Ich versuche, LabelEncoder von scikit-learn zu verwenden, um Pandas DataFrame von String-Labels zu kodieren. Da der Datenrahmen über viele (50+) Spalten verfügt, möchte ich vermeiden, dass für jede Spalte ein LabelEncoder-Objekt erstellt wird. Ich hätte lieber nur ein großes LabelEncoder-Objekt, das in all meinen Datenspalten funktioniert. 

Wenn Sie die gesamte DataFrame in LabelEncoder werfen, wird der folgende Fehler erzeugt. Bitte beachten Sie, dass ich hier Dummy-Daten verwende. In Wirklichkeit beschäftige ich mich mit etwa 50 Spalten mit Zeichenfolgen beschrifteten Daten. Ich brauche also eine Lösung, die keine Spalten nach Namen referenziert. 

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 (letzter Anruf zuletzt): Datei "", Zeile 1, in Datei "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py", Zeile 103, in passender Reihenfolge y = column_or_1d (y, warn = true) Datei "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py", Zeile 306 in Spalte_oder_1d erhöhen Sie ValueError ("falsche Eingabeform {0}". Format (Form)) ValueError: falsche Eingabeform (6, 3)

Irgendwelche Gedanken, wie man dieses Problem umgehen kann? 

155
Bryan

Sie können dies jedoch leicht tun,

df.apply(LabelEncoder().fit_transform)

BEARBEITEN:

Da diese Antwort über ein Jahr zurück liegt und viele positive Ergebnisse erzielt hat (einschließlich einer Prämie), sollte ich diese wahrscheinlich weiter ausbauen.

Für inverse_transform und transform müssen Sie ein wenig Hack ausführen.

from collections import defaultdict
d = defaultdict(LabelEncoder)

Damit behalten Sie jetzt alle Spalten LabelEncoder als Wörterbuch.

# 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))
319
Napitupulu Jon

Wie von larsmans erwähnt, verwendet LabelEncoder () nur ein 1-d-Array als Argument . Es ist jedoch ziemlich einfach, einen eigenen Label-Encoder zu rollen, der mit mehreren Spalten Ihrer Wahl arbeitet und einen transformierten Datenrahmen zurückgibt. Mein Code hier basiert zum Teil auf Zac Stewarts hervorragendem Blogpost hier .

Beim Erstellen eines benutzerdefinierten Encoders wird einfach eine Klasse erstellt, die auf die Methoden fit(), transform() und fit_transform() reagiert. In Ihrem Fall könnte ein guter Start etwa so aussehen:

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)

Nehmen wir an, wir möchten unsere zwei kategorialen Attribute (fruit und color) kodieren, das numerische Attribut weight jedoch allein lassen. Wir könnten das wie folgt machen:

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

Welcher wandelt unseren fruit_data-Datensatz ab

enter image description here zu 

enter image description here

Wenn Sie einen Datenrahmen übergeben, der vollständig aus kategorialen Variablen besteht, und den Parameter columns weglassen, wird jede Spalte codiert (was meiner Meinung nach das ist, wonach Sie ursprünglich gesucht haben):

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

Das verwandelt sich

enter image description here zu

enter image description here.

Beachten Sie, dass es wahrscheinlich verschluckt wird, wenn versucht wird, bereits numerische Attribute zu kodieren (fügen Sie ggf. Code hinzu, um dies zu handhaben).

Ein weiteres schönes Feature von Nizza ist, dass wir diesen benutzerdefinierten Transformator in einer Pipeline verwenden können:

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

Wir brauchen keinen LabelEncoder.

Sie können die Spalten in Kategorien umwandeln und dann deren Codes erhalten. Ich habe im Folgenden ein Wörterbuchverständnis verwendet, um diesen Prozess auf jede Spalte anzuwenden und das Ergebnis in einen Datenrahmen derselben Form mit identischen Indizes und Spaltennamen zurückzufassen.

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

Um ein Mapping-Wörterbuch zu erstellen, können Sie die Kategorien einfach anhand eines Wörterbuchverständnisses auflisten.

>>> {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'}}
11
Alexander

dies beantwortet Ihre Frage nicht direkt (für die Naputipulu Jon und PriceHardman fantastische Antworten haben)

Sie könnten jedoch für einige Klassifizierungsaufgaben usw. verwendet werden

pandas.get_dummies(input_df) 

dies kann einen Datenrahmen mit kategorialen Daten eingeben und einen Datenrahmen mit binären Werten zurückgeben. Variablenwerte werden im resultierenden Datenrahmen in Spaltennamen codiert. Mehr

6

Dies ist eineinhalb Jahre nach der Tatsache, aber auch ich musste in der Lage sein, mehrere Pandas-Dataframe-Spalten gleichzeitig zu .transform() (und sie auch .inverse_transform()). Dies erweitert den ausgezeichneten Vorschlag von @PriceHardman weiter oben:

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

    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

Beispiel:

Wenn df und df_copy() gemischte pandas-Datenframes sind, können Sie MultiColumnLabelEncoder() auf die dtype=object-Spalten folgendermaßen anwenden:

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

Sie können über Indizierung auf einzelne Spaltenklassen, Spaltenbeschriftungen und Spaltencodierer zugreifen, die zur Anpassung an jede Spalte verwendet werden:

mcle.all_classes_
mcle.all_encoders_
mcle.all_labels_

4

Angenommen, Sie versuchen lediglich, ein sklearn.preprocessing.LabelEncoder()-Objekt zu erhalten, das zur Darstellung Ihrer Spalten verwendet werden kann. Alles, was Sie tun müssen, ist:

le.fit(df.columns)

Im obigen Code haben Sie eine eindeutige Nummer, die jeder Spalte entspricht. Genauer gesagt, haben Sie eine 1: 1-Zuordnung von df.columns zu le.transform(df.columns.get_values()). Um die Kodierung einer Spalte zu erhalten, übergeben Sie sie einfach an le.transform(...). Als Beispiel erhält das Folgende die Kodierung für jede Spalte:

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

Angenommen, Sie möchten ein sklearn.preprocessing.LabelEncoder()-Objekt für alle Zeilenbeschriftungen erstellen, können Sie Folgendes tun:

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

In diesem Fall haben Sie höchstwahrscheinlich nicht eindeutige Zeilenbeschriftungen (wie in Ihrer Frage gezeigt). Um zu sehen, welche Klassen der Encoder erstellt hat, können Sie le.classes_ ausführen. Sie werden feststellen, dass dies die gleichen Elemente haben sollte wie in set(y for x in df.get_values() for y in x). Um eine Zeilenbeschriftung erneut in eine codierte Beschriftung zu konvertieren, verwenden Sie le.transform(...). Wenn Sie beispielsweise die Beschriftung für die erste Spalte im df.columns-Array und die erste Zeile abrufen möchten, können Sie Folgendes tun:

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

Die Frage, die Sie in Ihrem Kommentar hatten, ist etwas komplizierter, kann aber trotzdem noch erledigt werden:

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

Der obige Code bewirkt Folgendes:

  1. Erstellen Sie eine eindeutige Kombination aller Paare von (Spalte, Zeile).
  2. Stellen Sie jedes Paar als String-Version des Tupels dar. Dies ist eine Problemumgehung, um die LabelEncoder-Klasse zu umgehen, die keine Tupel als Klassennamen unterstützt.
  3. Passt die neuen Elemente an die LabelEncoder an.

Um dieses neue Modell zu verwenden, ist es etwas komplizierter. Angenommen, wir möchten die Darstellung für dasselbe Element extrahieren, das wir im vorherigen Beispiel nachgeschlagen haben (die erste Spalte in df.columns und die erste Zeile), können wir Folgendes tun:

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

Denken Sie daran, dass jede Suche jetzt eine Zeichenfolgendarstellung eines Tupels ist, der die Spalte (Spalte, Zeile) enthält.

4
TehTechGuy

Seit Scikit-Learn 0.20 können Sie sklearn.compose.ColumnTransformer und sklearn.preprocessing.OneHotEncoder verwenden:

Wenn Sie nur kategoriale Variablen haben, OneHotEncoder direkt:

from sklearn.preprocessing import OneHotEncoder

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

Wenn Sie über heterogen typisierte Features verfügen:

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)

Weitere Optionen in der Dokumentation: http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogene-data

3
ogrisel

Nein, LabelEncoder tut dies nicht. Es werden 1-d-Arrays von Klassenetiketten benötigt und 1-d-Arrays erzeugt. Es ist für die Behandlung von Klassenkennzeichnungen bei Klassifizierungsproblemen und nicht für willkürliche Daten konzipiert. Jeder Versuch, sie zu anderen Zwecken zu erzwingen, erfordert Code, um das eigentliche Problem in das Problem umzuwandeln, das es löst (und die Lösung zurück in den ursprünglichen Bereich).

2
Fred Foo

Im Anschluss an die Kommentare zur Lösung von @PriceHardman würde ich folgende Version der Klasse vorschlagen:

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

Diese Klasse passt den Encoder an das Trainingsset an und verwendet beim Transformieren die angepasste Version. Die ursprüngliche Version des Codes finden Sie hier .

1
Dror

wenn wir nur eine Spalte für die Labelcodierung und deren inverse Transformation verwenden, ist es einfach, wenn mehrere Spalten in Python vorhanden sind 

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
Puja Sharma

Ich habe den Quellcode ( https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/preprocessing/label.py ) von LabelEncoder überprüft. Es basiert auf einer Reihe von numpy-Transformationen, wobei eine davon np.unique () ist. Und diese Funktion erfordert nur 1-d-Array-Eingabe. (korrigiere mich, wenn ich falsch liege). 

Sehr grobe Ideen ... Ermitteln Sie zunächst, welche Spalten LabelEncoder benötigt haben, und durchlaufen Sie dann jede Spalte.

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

.__ Die zurückgegebene df wäre das nach dem encodieren und label_list zeigt Ihnen, was all diese Werte in der entsprechenden Spalte bedeuten. Dies ist ein Ausschnitt aus einem Datenverarbeitungsskript, das ich für die Arbeit geschrieben habe. Lassen Sie mich wissen, wenn Sie der Meinung sind, dass sich weitere Verbesserungen ergeben könnten.

EDIT: Ich möchte hier nur erwähnen, dass die oben genannten Methoden mit Datenrahmen funktionieren, ohne dass das Beste fehlt. Sie sind sich nicht sicher, wie sie auf den Datenrahmen hinarbeiten und fehlende Daten enthalten. (Ich hatte einen Deal mit fehlender Prozedur, bevor Sie die obigen Methoden ausführen.)

1
willaccc

Wenn Sie in Dataframe numerische und kategoriale Datentypen haben, können Sie Folgendes verwenden: Hier ist X mein Dataframe mit kategorialen und numerischen Variablen

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

Hinweis: Diese Technik ist gut, wenn Sie nicht daran interessiert sind, sie zurück zu konvertieren.

1
Vikas Gupta
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)

Hier lese ich eine csv vom Speicherort aus und in Funktion übergeben ich die Spaltenliste, die ich labelencode und den Datenrahmen, den ich verwenden möchte, anwenden möchte.

0
Rinki Nag

Hauptsächlich verwendete @Alexander-Antwort, musste jedoch einige Änderungen vornehmen - 

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

Um später wieder verwendet zu werden, können Sie die Ausgabe in einem Json-Dokument speichern. Wenn Sie es benötigen, lesen Sie es ein und verwenden die Funktion .map() wie oben.

0
bbennett36

Es ist möglich, dies alles direkt in Pandas zu erledigen und eignet sich gut für eine einzigartige Fähigkeit der Methode replace.

Lassen Sie uns zunächst ein Wörterbuch mit Wörterbüchern erstellen, in dem die Spalten und ihre Werte den neuen Ersetzungswerten zugeordnet werden.

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}}

Da dies immer eine Eins-zu-Eins-Zuordnung sein wird, können Sie das innere Wörterbuch invertieren, um eine Zuordnung der neuen Werte zum Original zu erhalten.

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

Jetzt können wir die einzigartige Fähigkeit der replace-Methode nutzen, um eine verschachtelte Liste von Wörterbüchern zu verwenden und die äußeren Schlüssel als Spalten und die inneren Schlüssel als Werte zu verwenden, die wir ersetzen möchten.

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

Wir können leicht zum Original zurückkehren, indem wir die replace-Methode erneut verketten

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
0
Ted Petrou

Nach langem Suchen und Experimentieren mit einigen Antworten hier und anderswo, denke ich, ist Ihre Antwort hier :

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

Dadurch werden Kategorienamen über Spalten hinweg beibehalten:

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
0
Christopher

Ein kurzer Weg zu LabelEncoder() mehreren Spalten mit einer 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])

und Sie können diesen le_dict verwenden, um jede andere Spalte zu kennzeichnen:

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

Das Problem ist die Form der Daten (pd dataframe), die Sie an die Fit-Funktion übergeben. Sie müssen die 1d-Liste übergeben.

0
ali sadr