Angenommen, ich habe eine, df
die Spalten von hat 'ID', 'col_1', 'col_2'
. Und ich definiere eine Funktion:
f = lambda x, y : my_function_expression
.
Jetzt möchte ich die beiden Spalten von to anwenden f
, um eine neue Spalte elementweise zu berechnen , ähnlich wie:df
'col_1', 'col_2'
'col_3'
df['col_3'] = df[['col_1','col_2']].apply(f)
# Pandas gives : TypeError: ('<lambda>() takes exactly 2 arguments (1 given)'
Wie macht man ?
** **. Fügen Sie ein Detailbeispiel wie unten hinzu ***.
import pandas as pd
df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']
def get_sublist(sta,end):
return mylist[sta:end+1]
#df['col_3'] = df[['col_1','col_2']].apply(get_sublist,axis=1)
# expect above to output df as below
ID col_1 col_2 col_3
0 1 0 1 ['a', 'b']
1 2 2 4 ['c', 'd', 'e']
2 3 3 5 ['d', 'e', 'f']
f
tun istAntworten:
Hier ist ein Beispiel
apply
für den Datenrahmen, mit dem ich anrufeaxis = 1
.Beachten Sie, dass der Unterschied darin besteht, anstatt zu versuchen, zwei Werte an die Funktion zu übergeben
f
, die Funktion neu zu schreiben, um ein Pandas-Serienobjekt zu akzeptieren, und dann die Serie zu indizieren, um die erforderlichen Werte zu erhalten.Abhängig von Ihrem Anwendungsfall ist es manchmal hilfreich, ein Pandas-
group
Objekt zu erstellen und es dannapply
für die Gruppe zu verwenden.quelle
sum
diese mit einer der bisher vorgeschlagenen Methoden erfolgreich gelöst wird.df
Ihnen definierte Objekt an. Ein anderer Ansatz (mit äquivalenten Ergebnissen) istdf.apply(lambda x: x[0] + x[1], axis = 1)
.In Pandas gibt es eine saubere, einzeilige Methode:
Dies erlaubt
f
eine benutzerdefinierte Funktion mit mehreren Eingabewerten und verwendet (sichere) Spaltennamen anstelle von (unsicheren) numerischen Indizes, um auf die Spalten zuzugreifen.Beispiel mit Daten (basierend auf der ursprünglichen Frage):
Ausgabe von
print(df)
:Wenn Ihre Spaltennamen Leerzeichen enthalten oder einen Namen mit einem vorhandenen Datenrahmenattribut teilen, können Sie mit eckigen Klammern indizieren:
quelle
axis=1
und Ihrer Spaltename
nicht Ihre Spaltendaten zurückgegeben werden, sondern dieindex
. Ähnlich wie bei dername
in agroupby()
. Ich habe dies gelöst, indem ich meine Spalte umbenannt habe..loc
das Beispiel zu bevorzugen . Dies kann erforderlich sein, wenn Sie dies an eine andere Problemeinstellung anpassen (z. B. Arbeiten mit Slices).Eine einfache Lösung ist:
quelle
Eine interessante Frage! meine Antwort wie folgt:
Ausgabe:
Ich habe den Spaltennamen in ID, J1, J2, J3 geändert, um sicherzustellen, dass ID <J1 <J2 <J3 ist, sodass die Spalte in der richtigen Reihenfolge angezeigt wird.
Noch eine kurze Version:
quelle
Die Methode, nach der Sie suchen, ist Series.combine. Es scheint jedoch, dass bei Datentypen einige Vorsicht geboten ist. In Ihrem Beispiel würden Sie (wie beim Testen der Antwort) naiv anrufen
Dies löst jedoch den Fehler aus:
Ich vermute, dass das Ergebnis vom selben Typ zu sein scheint wie die Reihe, die die Methode aufruft (df.col_1 hier). Folgendes funktioniert jedoch:
quelle
Die Art und Weise, wie Sie geschrieben haben, benötigt zwei Eingänge. Wenn Sie sich die Fehlermeldung ansehen, heißt es, dass Sie nicht zwei Eingänge für f bereitstellen, sondern nur einen. Die Fehlermeldung ist korrekt.
Die Nichtübereinstimmung liegt daran, dass df [['col1', 'col2']] einen einzelnen Datenrahmen mit zwei Spalten und nicht zwei separaten Spalten zurückgibt.
Sie müssen Ihr f so ändern, dass es eine einzelne Eingabe benötigt, den obigen Datenrahmen als Eingabe beibehalten und ihn dann innerhalb des Funktionskörpers in x, y aufteilen . Tun Sie dann alles, was Sie brauchen, und geben Sie einen einzelnen Wert zurück.
Sie benötigen diese Funktionssignatur, da die Syntax .apply (f) lautet. F muss also das einzelne Ding = Datenrahmen und nicht zwei Dinge verwenden, was Ihr aktuelles f erwartet.
Da Sie den Textkörper von f nicht angegeben haben, kann ich nicht mehr im Detail helfen - aber dies sollte den Ausweg bieten, ohne Ihren Code grundlegend zu ändern oder andere Methoden zu verwenden, anstatt ihn anzuwenden
quelle
Ich werde für np.vectorize abstimmen. Es ermöglicht Ihnen, nur über x Spalten zu schießen und sich nicht mit dem Datenrahmen in der Funktion zu befassen. Dies ist ideal für Funktionen, die Sie nicht steuern oder beispielsweise 2 Spalten und eine Konstante in eine Funktion senden (z. B. col_1, col_2, 'foo').
quelle
Das Zurückgeben einer Liste von
apply
ist eine gefährliche Operation, da nicht garantiert wird, dass das resultierende Objekt entweder eine Serie oder ein DataFrame ist. In bestimmten Fällen können Ausnahmen auftreten. Lassen Sie uns ein einfaches Beispiel durchgehen:Es gibt drei mögliche Ergebnisse bei der Rückgabe einer Liste von
apply
1) Wenn die Länge der zurückgegebenen Liste nicht der Anzahl der Spalten entspricht, wird eine Reihe von Listen zurückgegeben.
2) Wenn die Länge der zurückgegebenen Liste gleich der Anzahl der Spalten ist, wird ein DataFrame zurückgegeben und jede Spalte erhält den entsprechenden Wert in der Liste.
3) Wenn die Länge der zurückgegebenen Liste der Anzahl der Spalten für die erste Zeile entspricht, jedoch mindestens eine Zeile enthält, in der die Liste eine andere Anzahl von Elementen als die Anzahl der Spalten enthält, wird ein ValueError ausgelöst.
Beantwortung des Problems ohne Anwendung
Die Verwendung
apply
mit Achse = 1 ist sehr langsam. Mit grundlegenden iterativen Methoden ist es möglich, eine viel bessere Leistung (insbesondere bei größeren Datenmengen) zu erzielen.Erstellen Sie einen größeren Datenrahmen
Timings
@ Thomas Antwort
quelle
Ich bin sicher, dass dies nicht so schnell ist wie die Lösungen, die Pandas- oder Numpy-Operationen verwenden, aber wenn Sie Ihre Funktion nicht neu schreiben möchten, können Sie map verwenden. Verwendung der ursprünglichen Beispieldaten -
Auf diese Weise konnten wir so viele Argumente wie wir wollten in die Funktion übergeben. Die Ausgabe ist das, was wir wollten
quelle
apply
mitaxis=1
Mein Beispiel für Ihre Fragen:
quelle
Wenn Sie über einen großen Datensatz verfügen, können Sie dies mit swifter auf einfache, aber schnellere Weise (Ausführungszeit) tun:
quelle
Ich nehme an, Sie möchten die
get_sublist
Funktion nicht ändern und nur die DataFrame-apply
Methode verwenden, um die Aufgabe zu erledigen. Um das gewünschte Ergebnis zu erzielen, habe ich zwei Hilfefunktionen geschrieben:get_sublist_list
undunlist
. Wie der Funktionsname andeutet, rufen Sie zuerst die Liste der Unterlisten ab und extrahieren Sie dann die Unterliste aus dieser Liste. Schließlich müssen wir dieapply
Funktion aufrufen , um diese beiden Funktionen anschließend auf dendf[['col_1','col_2']]
DataFrame anzuwenden.Wenn Sie
[]
dieget_sublist
Funktion nicht einschließen , gibt dieget_sublist_list
Funktion eine einfache Liste zurück und wirdValueError: could not broadcast input array from shape (3) into shape (2)
ausgelöst, wie @Ted Petrou erwähnt hat.quelle