Wie man das bei Pandas macht:
Ich habe eine Funktion extract_text_features
für eine einzelne Textspalte, die mehrere Ausgabespalten zurückgibt. Insbesondere gibt die Funktion 6 Werte zurück.
Die Funktion funktioniert, es scheint jedoch keinen geeigneten Rückgabetyp (Pandas DataFrame / Numpy Array / Python-Liste) zu geben, sodass die Ausgabe korrekt zugewiesen werden kann df.ix[: ,10:16] = df.textcol.map(extract_text_features)
Also ich glaube , ich mit zu iterieren fallen müssen zurück df.iterrows()
, wie pro diese ?
UPDATE: Das Iterieren mit df.iterrows()
ist mindestens 20x langsamer, daher habe ich die Funktion aufgegeben und in sechs verschiedene .map(lambda ...)
Aufrufe aufgeteilt.
UPDATE 2: Diese Frage wurde um v0.11.0 zurück gestellt . Daher sind viele Fragen und Antworten nicht allzu relevant.
df.ix[: ,10:16]
. Ich denke, Sie müssenmerge
Ihre Funktionen in den Datensatz aufnehmen.apply
Antworten:
Aufbauend auf der Antwort von user1827356 können Sie die Zuweisung in einem Durchgang ausführen, indem Sie
df.merge
:BEARBEITEN: Bitte beachten Sie den enormen Speicherverbrauch und die niedrige Geschwindigkeit: https://ys-l.github.io/posts/2015/08/28/how-not-to-use-pandas-apply/ !
quelle
Normalerweise mache ich das mit
zip
:quelle
temp = list(zip(*df['num'].map(powers))); for i, c in enumerate(columns): df[c] = temp[c]
for i, c in enumerate(columns): df[c] = temp[i]
. Dank dessen habe ich wirklich den Zweck bekommenenumerate
: Dzip(*df['col'].map(function))
wahrscheinlich der richtige Weg.Das habe ich in der Vergangenheit getan
Der Vollständigkeit halber bearbeiten
quelle
df[['col1', 'col2']] = df['col3'].apply(lambda x: pd.Series('val1', 'val2'))
Dies ist in 95% der Anwendungsfälle der richtige und einfachste Weg, dies zu erreichen:
quelle
pd.Series({k:v})
und die Spaltenzuweisung wie in Ewans Antwort zu serialisieren?Im Jahr 2018 verwende ich
apply()
mit Argumentresult_type='expand'
quelle
pd.Series
was in Bezug auf Leistungsprobleme immer schön istdf.apply
zurückgibtdict
, werden die Spalten entsprechend den Schlüsseln benannt.Benutz einfach
result_type="expand"
quelle
Zusammenfassung: Wenn Sie nur einige Spalten erstellen möchten, verwenden Sie
df[['new_col1','new_col2']] = df[['data1','data2']].apply( function_of_your_choosing(x), axis=1)
Bei dieser Lösung muss die Anzahl der neuen Spalten, die Sie erstellen, der Anzahl der Spalten entsprechen, die Sie als Eingabe für die Funktion .apply () verwenden. Wenn Sie etwas anderes tun möchten, schauen Sie sich die anderen Antworten an.
Einzelheiten Angenommen, Sie haben einen zweispaltigen Datenrahmen. Die erste Spalte gibt die Größe einer Person an, wenn sie 10 Jahre alt ist. Die zweite ist die Größe der Person, wenn sie 20 Jahre alt ist.
Angenommen, Sie müssen sowohl den Mittelwert der Körpergröße jeder Person als auch die Summe der Körpergröße jeder Person berechnen. Das sind zwei Werte pro Zeile.
Sie können dies über die folgende Funktion tun, die in Kürze angewendet wird:
Sie können diese Funktion folgendermaßen verwenden:
(Um es klar auszudrücken: Diese Apply-Funktion nimmt die Werte aus jeder Zeile im untergeordneten Datenrahmen auf und gibt eine Liste zurück.)
Wenn Sie dies jedoch tun:
Sie erstellen eine neue Spalte mit den Listen [Mittelwert, Summe], die Sie vermutlich vermeiden möchten, da hierfür ein weiteres Lambda / Apply erforderlich wäre.
Stattdessen möchten Sie jeden Wert in eine eigene Spalte aufteilen. Dazu können Sie zwei Spalten gleichzeitig erstellen:
quelle
df["mean"], df["sum"] = df[['height_at_age_10','height_at_age_20']] .apply(mean_and_sum(x),axis=1)
return pd.Series([mean,sum])
Bei mir hat das geklappt:
Eingabe df
Funktion
Erstellen Sie 2 neue Spalten:
Ausgabe:
quelle
Ich habe nach verschiedenen Möglichkeiten gesucht, und die hier gezeigte Methode (Rückgabe einer Pandas-Serie) scheint nicht am effizientesten zu sein.
Wenn wir mit einem größeren Datenrahmen aus zufälligen Daten beginnen:
Das hier gezeigte Beispiel:
Eine alternative Methode:
Nach meiner Einschätzung ist es weitaus effizienter, eine Reihe von Tupeln zu nehmen und diese dann in einen DataFrame zu konvertieren. Es würde mich jedoch interessieren, wenn die Leute denken, wenn es einen Fehler in meiner Arbeit gibt.
quelle
Die akzeptierte Lösung wird für viele Daten extrem langsam sein. Die Lösung mit der größten Anzahl von Upvotes ist etwas schwer zu lesen und auch mit numerischen Daten langsam. Wenn jede neue Spalte unabhängig von den anderen berechnet werden kann, würde ich sie einfach direkt zuweisen, ohne sie zu verwenden
apply
.Beispiel mit gefälschten Zeichendaten
Erstellen Sie 100.000 Zeichenfolgen in einem DataFrame
Angenommen, wir wollten einige Textfunktionen extrahieren, wie in der ursprünglichen Frage beschrieben. Lassen Sie uns zum Beispiel das erste Zeichen extrahieren, das Vorkommen des Buchstabens 'e' zählen und die Phrase groß schreiben.
Timings
Überraschenderweise können Sie eine bessere Leistung erzielen, indem Sie jeden Wert durchlaufen
Ein weiteres Beispiel mit gefälschten numerischen Daten
Erstellen Sie 1 Million Zufallszahlen und testen Sie die
powers
Funktion von oben.Das Zuweisen jeder Spalte ist 25x schneller und gut lesbar:
Ich habe hier eine ähnliche Antwort mit weiteren Details gegeben, warum dies
apply
normalerweise nicht der richtige Weg ist.quelle
Habe die gleiche Antwort in zwei anderen ähnlichen Fragen gepostet. Ich bevorzuge dies, indem ich die Rückgabewerte der Funktion in einer Reihe zusammenfasse:
Verwenden Sie anschließend "Anwenden" wie folgt, um separate Spalten zu erstellen:
quelle
Sie können die gesamte Zeile anstelle von Werten zurückgeben:
Dabei gibt die Funktion die Zeile zurück
quelle
extract_text_features
auf jede Spalte des df anwenden , sondern nur auf diedf.textcol
Das hat bei mir funktioniert. Neue Spalte wird mit verarbeiteten alten Spaltendaten erstellt.
quelle