Ich versuche, Scikit-Learns zu verwenden LabelEncoder
, um Pandas DataFrame
von String-Labels zu codieren . Da der Datenrahmen viele (50+) Spalten enthält, möchte ich vermeiden, LabelEncoder
für jede Spalte ein Objekt zu erstellen . Ich hätte lieber nur ein großes LabelEncoder
Objekt, das in allen meinen Datenspalten funktioniert .
Wenn Sie das Ganze DataFrame
in werfen, LabelEncoder
entsteht der folgende Fehler. Bitte beachten Sie, dass ich hier Dummy-Daten verwende. Tatsächlich habe ich es mit ungefähr 50 Spalten mit Daten mit Zeichenfolgenbeschriftung zu tun. Benötigen Sie 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 Aufruf zuletzt): Datei "", Zeile 1, in Datei "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py", Zeile 103, in fit y = column_or_1d (y, warn = True) Datei "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py", Zeile 306, in column_or_1d erhöhen ValueError ("fehlerhafte Eingabeform { 0} ". Format (Form)) ValueError: falsche Eingabeform (6, 3)
Irgendwelche Gedanken darüber, wie man dieses Problem umgehen kann?
quelle
dataframe
Zeichenfolgendaten. Ich picke die Codierungsobjekte, möchte also vermeiden, dass 50 separate Objekte ausgewählt / entfernt werden müssen. Ich frage mich auch, ob es eine Möglichkeit gibt, dass der Encoder die Daten vereinfacht, dh nur eine Zeile mit einem Bezeichner für jede eindeutige Kombination von Variablen in jeder Spalte zurückgibt.replace
Methode übergeben. Siehe diese Antwort untenAntworten:
Sie können dies jedoch leicht tun,
EDIT2:
In scikit-learn 0.20 wird empfohlen
da der OneHotEncoder jetzt die Eingabe von Zeichenfolgen unterstützt. Mit dem ColumnTransformer ist es möglich, OneHotEncoder nur auf bestimmte Spalten anzuwenden.
BEARBEITEN:
Da diese Antwort vor über einem Jahr stammt und viele positive Stimmen (einschließlich eines Kopfgeldes) hervorgerufen hat, sollte ich sie wahrscheinlich weiter ausbauen.
Für inverse_transform und transform musst du ein bisschen hacken.
Damit behalten Sie jetzt alle Spalten
LabelEncoder
als Wörterbuch bei.quelle
df.apply(LabelEncoder().fit_transform)
?LabelBinarizer
stattdessen zu arbeiten und das Wörterbuch für einen Testsatz wiederzuverwenden? Ich habe es versuchtd = defaultdict(LabelBinarizer)
und dann wirdfit = df.apply(lambda x: d[x.name].fit_transform(x))
aber eine Ausnahme ausgelöst :Exception: Data must be 1-dimensional
. Ich bin mir nicht sicher, wie der resultierende DataFrame aussehen soll ... Vielleicht sollte jede Spalte die binärisierten Vektoren enthalten.Wie von larsmans erwähnt, verwendet LabelEncoder () nur ein 1-d-Array als Argument . Es ist jedoch recht einfach, einen eigenen Beschriftungscodierer zu erstellen, der mit mehreren Spalten Ihrer Wahl arbeitet und einen transformierten Datenrahmen zurückgibt. Mein Code hier basiert teilweise auf Zac Stewarts ausgezeichnetem Blog-Beitrag, der hier zu finden ist .
Erstellen einer Klasse , dass reagiert auf die beinhaltet einfach einen benutzerdefinierten Encoder Erstellen
fit()
,transform()
undfit_transform()
Methoden. In Ihrem Fall könnte ein guter Start ungefähr so aussehen:Angenommen, wir möchten unsere beiden kategorialen Attribute (
fruit
undcolor
) codieren und dabei das numerische Attribut inweight
Ruhe lassen. Wir könnten dies wie folgt tun:Welches transformiert unseren
fruit_data
Datensatz vonzu
Wenn Sie ihm einen Datenrahmen übergeben, der ausschließlich aus kategorialen Variablen besteht, und den
columns
Parameter weglassen , wird jede Spalte codiert (was meiner Meinung nach ursprünglich gesucht wurde):Das verwandelt sich
zu
.
Beachten Sie, dass es wahrscheinlich erstickt, wenn versucht wird, bereits numerische Attribute zu codieren (fügen Sie Code hinzu, um dies zu handhaben, wenn Sie möchten).
Ein weiteres nettes Feature ist, dass wir diesen benutzerdefinierten Transformator in einer Pipeline verwenden können:
quelle
Seit scikit-learn 0.20 können Sie verwenden
sklearn.compose.ColumnTransformer
undsklearn.preprocessing.OneHotEncoder
:Wenn Sie nur kategoriale Variablen haben,
OneHotEncoder
direkt:Wenn Sie heterogen typisierte Funktionen haben:
Weitere Optionen in der Dokumentation: http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogene-data
quelle
inverse_transform()
wird von ColumnTransformer jedoch nicht unterstützt. Zumindest momentan nicht: github.com/scikit-learn/scikit-learn/issues/11463 . Das ist ein großer Nachteil für meine Bewerbung und wird wahrscheinlich auch für andere sein.Wir brauchen keinen LabelEncoder.
Sie können die Spalten in Kategorien konvertieren und dann ihre Codes abrufen. Ich habe unten ein Wörterbuchverständnis verwendet, um diesen Prozess auf jede Spalte anzuwenden und das Ergebnis wieder in einen Datenrahmen derselben Form mit identischen Indizes und Spaltennamen zu verpacken.
Um ein Zuordnungswörterbuch zu erstellen, können Sie die Kategorien einfach mithilfe eines Wörterbuchverständnisses auflisten:
quelle
Dies beantwortet Ihre Frage nicht direkt (auf die Naputipulu Jon und PriceHardman fantastische Antworten haben).
Für einige Klassifizierungsaufgaben usw. können Sie diese jedoch verwenden
Dies kann einen Datenrahmen mit kategorialen Daten eingeben und einen Datenrahmen mit Binärwerten zurückgeben. Variablenwerte werden im resultierenden Datenrahmen in Spaltennamen codiert. Mehr
quelle
Angenommen, Sie versuchen lediglich, ein
sklearn.preprocessing.LabelEncoder()
Objekt zu erhalten, mit dem Ihre Spalten dargestellt werden können, müssen Sie lediglich Folgendes tun:Im obigen Code haben Sie eine eindeutige Nummer, die jeder Spalte entspricht. Genauer gesagt erhalten Sie eine 1: 1-Zuordnung von
df.columns
zule.transform(df.columns.get_values())
. Um die Codierung einer Spalte zu erhalten, übergeben Sie sie einfach anle.transform(...)
. Im Folgenden wird beispielsweise die Codierung für jede Spalte angegeben:Angenommen, Sie möchten ein
sklearn.preprocessing.LabelEncoder()
Objekt für alle Ihre Zeilenbeschriftungen erstellen , können Sie Folgendes tun: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 dies tun
le.classes_
. Sie werden feststellen, dass dies die gleichen Elemente wie in haben sollteset(y for x in df.get_values() for y in x)
. Verwenden Sie erneut, um eine Zeilenbeschriftung in eine codierte Beschriftung umzuwandelnle.transform(...)
. Wenn Sie beispielsweise die Bezeichnung für die erste Spalte imdf.columns
Array und die erste Zeile abrufen möchten , können Sie Folgendes tun:Die Frage, die Sie in Ihrem Kommentar hatten, ist etwas komplizierter, kann aber dennoch beantwortet werden:
Der obige Code bewirkt Folgendes:
LabelEncoder
Klasse zu überwinden, die keine Tupel als Klassennamen unterstützt.LabelEncoder
.Die Verwendung dieses neuen Modells ist 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 dies tun:
Denken Sie daran, dass jede Suche jetzt eine Zeichenfolgendarstellung eines Tupels ist, das die (Spalte, Zeile) enthält.
quelle
Nein,
LabelEncoder
macht das nicht. Es werden 1-D-Arrays von Klassenbezeichnungen verwendet und 1-D-Arrays erstellt. Es wurde entwickelt, um Klassenbeschriftungen bei Klassifizierungsproblemen zu behandeln, nicht bei willkürlichen Daten. Für jeden Versuch, sie für andere Zwecke zu erzwingen, ist Code erforderlich, um das eigentliche Problem in das gelöste Problem (und die Lösung zurück in den ursprünglichen Bereich) umzuwandeln.quelle
DataFrame
?LabelEncoder
Code an und passe ihn an. Ich benutze Pandas nicht selbst, also weiß ich nicht, wie schwer das sein wird.pandas
Leute bei dieser Frage eine Pause einlegen lassen - ich bin sicher, dass ich nicht die einzige Person mit dieser Herausforderung bin, also hoffe ich, dass es da draußen eine vorgefertigte Lösung gibt.Dies ist eineinhalb Jahre später, aber auch ich musste in der Lage sein,
.transform()
mehrere Pandas-Datenrahmenspalten gleichzeitig zu erstellen (und auch in der Lage zu.inverse_transform()
sein). Dies erweitert den hervorragenden Vorschlag von @PriceHardman oben:Beispiel:
Wenn
df
unddf_copy()
gemischtepandas
Datenrahmen sind, können Sie dieMultiColumnLabelEncoder()
aufdtype=object
folgende Weise auf die Spalten anwenden :Sie können über die Indizierung auf einzelne Spaltenklassen, Spaltenbeschriftungen und Spaltencodierer zugreifen, die für jede Spalte verwendet werden:
mcle.all_classes_
mcle.all_encoders_
mcle.all_labels_
quelle
fit
Methode von oben verwendet haben, die erst dann Etiketten erzeugt, wenn Sie sie anwenden (transform
/fit_transform
) die Daten.Nach den Kommentaren zur Lösung von @PriceHardman würde ich die folgende Version der Klasse vorschlagen:
Diese Klasse passt zum Encoder des Trainingssatzes und verwendet beim Transformieren die angepasste Version. Die erste Version des Codes finden Sie hier .
quelle
Ein kurzer Weg zu
LabelEncoder()
mehreren Spalten mit einemdict()
:und Sie können dies verwenden
le_dict
, um jede andere Spalte zu kennzeichnen:quelle
Es ist möglich, dies alles direkt in Pandas zu tun und ist für eine einzigartige Fähigkeit der
replace
Methode gut geeignet .Lassen Sie uns zunächst ein Wörterbuch mit Wörterbüchern erstellen, in denen die Spalten und ihre Werte ihren neuen Ersatzwerten zugeordnet werden.
Da dies immer eine Eins-zu-Eins-Zuordnung ist, können wir das innere Wörterbuch invertieren, um eine Zuordnung der neuen Werte zum Original wiederherzustellen.
Jetzt können wir die einzigartige Fähigkeit der
replace
Methode nutzen, um eine verschachtelte Liste von Wörterbüchern zu erstellen und die äußeren Schlüssel als Spalten und die inneren Schlüssel als Werte zu verwenden, die wir ersetzen möchten.Wir können leicht zum Original zurückkehren, indem wir die
replace
Methode erneut verkettenquelle
Nach vielen Suchen und Experimenten mit einigen Antworten hier und anderswo denke ich, dass Ihre Antwort hier ist :
Dadurch bleiben Kategorienamen über Spalten hinweg erhalten:
quelle
Ich habe den Quellcode ( https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/preprocessing/label.py ) von LabelEncoder überprüft. Es basierte auf einer Reihe von Numpy-Transformationen, von denen eine np.unique () ist. Und diese Funktion akzeptiert nur 1-d-Array-Eingaben. (Korrigieren Sie mich, wenn ich falsch liege).
Sehr grobe Ideen ... Identifizieren Sie zuerst, welche Spalten LabelEncoder benötigen, und durchlaufen Sie dann jede Spalte.
Der zurückgegebene df ist derjenige nach der Codierung, und label_list zeigt Ihnen, was all diese Werte in der entsprechenden Spalte bedeuten. Dies ist ein Ausschnitt aus einem Datenprozess-Skript, das ich für die Arbeit geschrieben habe. Lassen Sie mich wissen, wenn Sie glauben, dass es weitere Verbesserungen geben könnte.
EDIT: Ich möchte hier nur erwähnen, dass die oben genannten Methoden mit Datenrahmen funktionieren, ohne dass die besten fehlen. Nicht sicher, wie es in Richtung Datenrahmen funktioniert, enthält fehlende Daten. (Ich hatte ein Problem mit fehlenden Prozeduren, bevor ich die obigen Methoden ausführte.)
quelle
Wenn wir eine einzelne Spalte haben, um die Etikettencodierung durchzuführen, und ihre inverse Transformation, ist es einfach, wie es geht, wenn es mehrere Spalten in Python gibt
quelle
Wenn Sie beide Arten von Daten im Datenrahmen numerisch und kategorisch haben, können Sie Folgendes verwenden: Hier ist X mein Datenrahmen, der beide Variablen kategorisch und numerisch enthält
Hinweis: Diese Technik ist gut, wenn Sie nicht daran interessiert sind, sie zurück zu konvertieren.
quelle
Verwenden von Neuraxle
Mit dieser Methode kann Ihr Label-Encoder in eine reguläre Scikit-Lern-Pipeline passen und diese transformieren . Importieren wir einfach:
Gleicher gemeinsam genutzter Encoder für Spalten:
So wird ein gemeinsam genutzter LabelEncoder auf alle Daten angewendet, um sie zu codieren:
Ergebnis:
Unterschiedliche Encoder pro Spalte:
Und so wird ein erster eigenständiger LabelEncoder auf die Haustiere angewendet, und ein zweiter wird für den Spaltenbesitzer und den Standort freigegeben. Um genau zu sein, haben wir hier eine Mischung aus verschiedenen und gemeinsam genutzten Label-Encodern:
Ergebnis:
quelle
Hauptsächlich verwendete @ Alexander Antwort, musste aber einige Änderungen vornehmen -
Für eine spätere Wiederverwendung können Sie die Ausgabe einfach in einem JSON-Dokument speichern. Wenn Sie sie benötigen, lesen Sie sie ein und verwenden die oben beschriebene
.map()
Funktion.quelle
Das Problem ist die Form der Daten (pd dataframe), die Sie an die Anpassungsfunktion übergeben. Sie müssen 1d Liste bestehen.
quelle
Hier lese ich eine CSV von Ort und in Funktion übergebe ich die Spaltenliste, die ich kennzeichnen möchte, und den Datenrahmen, den ich anwenden möchte.
quelle
Wie wäre es damit?
Es ist nicht das effizienteste, aber es funktioniert und es ist super einfach.
quelle