web-dev-qa-db-de.com

label-Encoder-Codierung der fehlenden Werte

Ich verwende den Label Encoder, um kategoriale Daten in numerische Werte umzuwandeln.

Wie geht LabelEncoder mit fehlenden Werten um?

from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
le = LabelEncoder()
le.fit_transform(a)

Ausgabe:

array([1, 2, 3, 0, 4, 1])

Für das obige Beispiel hat der Etikettencodierer die NaN-Werte in eine Kategorie geändert. Woher weiß ich, welche Kategorie fehlende Werte darstellt?

19
saurabh agarwal

Verwenden Sie keine LabelEncoder mit fehlenden Werten. Ich weiß nicht, welche Version von scikit-learn Sie verwenden, aber in 0.17.1 führt Ihr Code TypeError: unorderable types: str() > float() aus.

Wie Sie in der Quelle sehen können, verwendet numpy.unique die zu codierenden Daten, wodurch TypeError ausgelöst wird, wenn fehlende Werte gefunden werden. Wenn Sie fehlende Werte kodieren möchten, ändern Sie zunächst den Typ in eine Zeichenfolge:

a[pd.isnull(a)]  = 'NaN'
10
dukebody

Hallo ein kleiner Rechenhack, den ich für meine eigene Arbeit gemacht habe:

from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
le = LabelEncoder()
### fit with the desired col, col in position 0 for this example
fit_by = pd.Series([i for i in a.iloc[:,0].unique() if type(i) == str])
le.fit(fit_by)
### Set transformed col leaving np.NaN as they are
a["transformed"] = fit_by.apply(lambda x: le.transform([x])[0] if type(x) == str else x)
3
Kerem T

Sie können die Werte mit einem Wert füllen und den Datentyp der Datenspalte in eine Zeichenfolge ändern, damit alles funktioniert.

from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
a.fillna(99)
le = LabelEncoder()
le.fit_transform(a.astype(str))
2
raghu nanden

Dies ist meine Lösung, weil ich mit den hier veröffentlichten Lösungen nicht zufrieden war. Ich brauchte einen LabelEncoder, der meine fehlenden Werte als 'NaN' enthält, um anschließend einen Imputer zu verwenden. Also habe ich meine eigene LabelEncoder-Klasse geschrieben. Es funktioniert mit DataFrames.

from sklearn.base import BaseEstimator
from sklearn.base import TransformerMixin
from sklearn.preprocessing import LabelEncoder

class LabelEncoderByCol(BaseEstimator, TransformerMixin):
    def __init__(self,col):
        #List of column names in the DataFrame that should be encoded
        self.col = col
        #Dictionary storing a LabelEncoder for each column
        self.le_dic = {}
        for el in self.col:
            self.le_dic[el] = LabelEncoder()

    def fit(self,x,y=None):
        #Fill missing values with the string 'NaN'
        x[self.col] = x[self.col].fillna('NaN')
        for el in self.col:
            #Only use the values that are not 'NaN' to fit the Encoder
            a = x[el][x[el]!='NaN']
            self.le_dic[el].fit(a)
        return self

    def transform(self,x,y=None):
        #Fill missing values with the string 'NaN'
        x[self.col] = x[self.col].fillna('NaN')
        for el in self.col:
            #Only use the values that are not 'NaN' to fit the Encoder
            a = x[el][x[el]!='NaN']
            #Store an ndarray of the current column
            b = x[el].get_values()
            #Replace the elements in the ndarray that are not 'NaN'
            #using the transformer
            b[b!='NaN'] = self.le_dic[el].transform(a)
            #Overwrite the column in the DataFrame
            x[el]=b
        #return the transformed DataFrame
        return x

Sie können einen DataFrame eingeben, nicht nur eine 1-dim-Serie. Mit col können Sie die Spalten auswählen, die codiert werden sollen.

Ich möchte hier etwas Feedback geben.

2

sie können auch eine Maske verwenden, um den ursprünglichen Datenrahmen nach der Beschriftung zu ersetzen

df = pd.DataFrame({'A': ['x', np.NaN, 'z'], 'B': [1, 6, 9], 'C': [2, 1, np.NaN]})

    A   B   C
0   x   1   2.0
1   NaN 6   1.0
2   z   9   NaN

dfTmp = df
mask = df_1.isnull()
       A    B   C
0   False   False   False
1   True    False   False
2   False   False   True

df = df.astype(str).apply(LabelEncoder().fit_transform)
df.where(~mask, original)

A   B   C
0   1.0 0   1.0
1   NaN 1   0.0
2   2.0 2   NaN
1
ulrich

Ich wollte auch meinen Workaround beisteuern, da ich die anderen etwas mühsamer fand, wenn ich mit kategorialen Daten arbeitete, die fehlende Werte enthielten

# Create a random dataframe
foo = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))

# Randomly intersperse column 'A' with missing data (NaN)
foo['A'][np.random.randint(0,len(foo), size=20)] = np.nan

# Convert this series to string, to simulate our problem
series = foo['A'].astype(str)

# np.nan are converted to the string "nan", mask these out
mask = (series == "nan")

# Apply the LabelEncoder to the unmasked series, replace the masked series with np.nan
series[~mask] = LabelEncoder().fit_transform(series[~mask])
series[mask] = np.nan

foo['A'] = series
0
rorance_

Ich hatte das gleiche Problem, aber nichts davon arbeitete für mich. Also fügte ich den Trainingsdaten eine neue Zeile hinzu, die nur aus "nan" bestand.

0
silent_dev

Folgende Geberadressen Keine Werte in jeder Kategorie.

class MultiColumnLabelEncoder:
    def __init__(self):
        self.columns = None
        self.led = defaultdict(preprocessing.LabelEncoder)

    def fit(self, X):
        self.columns = X.columns
        for col in self.columns:
            cat = X[col].unique()
            cat = [x if x is not None else "None" for x in cat]
            self.led[col].fit(cat)
        return self

    def fit_transform(self, X):
        if self.columns is None:
            self.fit(X)
        return self.transform(X)

    def transform(self, X):
        return X.apply(lambda x:  self.led[x.name].transform(x.apply(lambda e: e if e is not None else "None")))

    def inverse_transform(self, X):
        return X.apply(lambda x: self.led[x.name].inverse_transform(x))

Verwendungsbeispiel

df = pd.DataFrame({
    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
    'owner': ['Champ', 'Ron', 'Brick', None, 'Veronica', 'Ron'],
    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
                 None]
})


print(df)

   location     owner    pets
0  San_Diego     Champ     cat
1   New_York       Ron     dog
2   New_York     Brick     cat
3  San_Diego      None  monkey
4  San_Diego  Veronica     dog
5       None       Ron     dog

le = MultiColumnLabelEncoder()
le.fit(df)

transformed = le.transform(df)
print(transformed)

   location  owner  pets
0         2      1     0
1         0      3     1
2         0      0     0
3         2      2     2
4         2      4     1
5         1      3     1

inverted = le.inverse_transform(transformed)
print(inverted)

        location     owner    pets
0  San_Diego     Champ     cat
1   New_York       Ron     dog
2   New_York     Brick     cat
3  San_Diego      None  monkey
4  San_Diego  Veronica     dog
5       None       Ron     dog
0

Die am häufigsten gewählte Antwort von @Kerem enthält Tippfehler. Daher veröffentliche ich die korrigierte und verbesserte Antwort hier:

from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
for j in a.columns.values:
    le = LabelEncoder()
### fit with the desired col, col in position 0 for this ###example
    fit_by = pd.Series([i for i in a[j].unique() if type(i) == str])
    le.fit(fit_by)
    ### Set transformed col leaving np.NaN as they are
    a["transformed"] = a[j].apply(lambda x: le.transform([x])[0] if type(x) == str else x)

0
prony

Ein einfacher Weg ist das

Es ist ein Beispiel für Titanic

LABEL_COL = ["Sex", "Embarked"]

def label(df):
    _df = df.copy()
    le = LabelEncoder()
    for col in LABEL_COL:
        # Not NaN index
        idx = ~_df[col].isna()
        _df.loc[idx, col] \
            = le.fit(_df.loc[idx, col]).transform(_df.loc[idx, col])
    return _df
0
chankane

So habe ich es gemacht:

import pandas as pd
from sklearn.preprocessing import LabelEncoder

UNKNOWN_TOKEN = '<unknown>'
a = pd.Series(['A','B','C', 'D','A'], dtype=str).unique().tolist()
a.append(UNKNOWN_TOKEN)
le = LabelEncoder()
le.fit_transform(a)
embedding_map = dict(Zip(le.classes_, le.transform(le.classes_)))

und bei Beantragung neuer Testdaten:

test_df = test_df.apply(lambda x: x if x in embedding_map else UNKNOWN_TOKEN)
le.transform(test_df)
0
muon