Die Dokumente zeigen, wie Sie mehrere Funktionen gleichzeitig auf ein Groupby-Objekt anwenden, indem Sie ein Diktat mit den Namen der Ausgabespalten als Schlüssel verwenden:
In [563]: grouped['D'].agg({'result1' : np.sum,
.....: 'result2' : np.mean})
.....:
Out[563]:
result2 result1
A
bar -0.579846 -1.739537
foo -0.280588 -1.402938
Dies funktioniert jedoch nur bei einem Series groupby-Objekt. Und wenn ein Diktat auf ähnliche Weise an eine Gruppe von DataFrame übergeben wird, erwartet es, dass die Schlüssel die Spaltennamen sind, auf die die Funktion angewendet wird.
Ich möchte mehrere Funktionen auf mehrere Spalten anwenden (bestimmte Spalten werden jedoch mehrmals bearbeitet). Außerdem hängen einige Funktionen auf anderen Spalten in dem groupby Objekt (wie SUMIF Funktionen). Meine derzeitige Lösung besteht darin, Spalte für Spalte zu gehen und so etwas wie den obigen Code auszuführen, wobei Lambdas für Funktionen verwendet werden, die von anderen Zeilen abhängen. Dies dauert jedoch lange (ich denke, es dauert lange, bis ein Groupby-Objekt durchlaufen ist). Ich muss es so ändern, dass ich das gesamte groupby-Objekt in einem einzigen Lauf durchlaufe, aber ich frage mich, ob es in Pandas eine eingebaute Methode gibt, um dies etwas sauber zu machen.
Zum Beispiel habe ich so etwas versucht
grouped.agg({'C_sum' : lambda x: x['C'].sum(),
'C_std': lambda x: x['C'].std(),
'D_sum' : lambda x: x['D'].sum()},
'D_sumifC3': lambda x: x['D'][x['C'] == 3].sum(), ...)
aber wie erwartet bekomme ich einen KeyError (da die Schlüssel eine Spalte sein müssen, wenn agg
sie von einem DataFrame aufgerufen werden).
Gibt es eine eingebaute Möglichkeit, das zu tun, was ich tun möchte, oder die Möglichkeit, dass diese Funktionalität hinzugefügt wird, oder muss ich die Gruppe nur manuell durchlaufen?
Vielen Dank
Antworten:
Die zweite Hälfte der derzeit akzeptierten Antwort ist veraltet und weist zwei Abwertungen auf. Erstens und vor allem können Sie kein Wörterbuch mit Wörterbüchern mehr an die
agg
groupby-Methode übergeben. Zweitens nie verwenden.ix
.Wenn Sie mit zwei separaten Spalten gleichzeitig arbeiten möchten, würde ich die Verwendung der
apply
Methode vorschlagen, die implizit einen DataFrame an die angewendete Funktion übergibt. Verwenden wir einen ähnlichen Datenrahmen wie den von obenEin Wörterbuch, das von Spaltennamen auf Aggregationsfunktionen abgebildet wird, ist immer noch eine perfekte Möglichkeit, eine Aggregation durchzuführen.
Wenn Ihnen dieser hässliche Lambda-Spaltenname nicht gefällt, können Sie eine normale Funktion verwenden und dem speziellen
__name__
Attribut wie folgt einen benutzerdefinierten Namen geben :Verwenden
apply
und Zurückgeben einer SerieWenn Sie mehrere Spalten hatten, die miteinander interagieren mussten, können Sie diese nicht verwenden
agg
, wodurch implizit eine Reihe an die Aggregationsfunktion übergeben wird. Bei Verwendungapply
der gesamten Gruppe als DataFrame wird an die Funktion übergeben.Ich empfehle, eine einzelne benutzerdefinierte Funktion zu erstellen, die eine Reihe aller Aggregationen zurückgibt. Verwenden Sie den Serienindex als Beschriftung für die neuen Spalten:
Wenn Sie in MultiIndexes verliebt sind, können Sie dennoch eine Serie mit einer solchen zurückgeben:
quelle
a
innerhalb der Gruppe0
nicht sein0.418500 + 0.446069 = 0.864569
? Gleiches gilt für andere Zellen, die Zahlen scheinen sich nicht zu summieren. Könnte es sein, dass in den folgenden Beispielen ein etwas anderer zugrunde liegender Datenrahmen verwendet wurde?Im ersten Teil können Sie ein Diktat mit Spaltennamen für Schlüssel und eine Liste mit Funktionen für die Werte übergeben:
UPDATE 1:
Da die Aggregatfunktion für Serien funktioniert, gehen Verweise auf die anderen Spaltennamen verloren. Um dies zu umgehen, können Sie auf den vollständigen Datenrahmen verweisen und ihn mithilfe der Gruppenindizes innerhalb der Lambda-Funktion indizieren.
Hier ist eine hackige Problemumgehung:
Hier besteht die resultierende 'D'-Spalte aus den summierten' E'-Werten.
UPDATE 2:
Hier ist eine Methode, von der ich denke, dass sie alles tut, was Sie verlangen. Erstellen Sie zuerst eine benutzerdefinierte Lambda-Funktion. Unten verweist g auf die Gruppe. Bei der Aggregation ist g eine Reihe. Übergeben
g.index
andf.ix[]
wählt die aktuelle Gruppe aus df aus. Ich teste dann, ob Spalte C kleiner als 0,5 ist. Die zurückgegebene boolesche Reihe wird übergeben, ang[]
die nur die Zeilen ausgewählt werden, die die Kriterien erfüllen.quelle
{funcname: func}
anstelle von Listen auch ein Diktat als Werte übergeben, um meine benutzerdefinierten Namen beizubehalten. In beiden Fällen kann ich jedoch keine übergebenlambda
, die andere Spalten verwendet (wielambda x: x['D'][x['C'] < 3].sum()
oben: "KeyError: 'D'"). Irgendeine Idee, ob das möglich ist?KeyError: 'D'
df['A'].ix[g.index][df['C'] < 0].sum()
. Dies wird jedoch langsam ziemlich chaotisch - ich denke, aus Gründen der Lesbarkeit ist eine manuelle Schleife vorzuziehen, und ich bin mir nicht sicher, ob es eine Möglichkeit gibt, demagg
Argument meinen bevorzugten Namen zu geben (anstelle von<lambda>
). Ich hoffe, dass jemand einen einfacheren Weg kennt ...{'D': {'my name':lambda function}}
der innere Diktatschlüssel zum Spaltennamen wird.Als Alternative (hauptsächlich in Bezug auf Ästhetik) zu Ted Petrous Antwort fand ich, dass ich eine etwas kompaktere Auflistung bevorzugte. Bitte akzeptieren Sie es nicht, es ist nur ein viel detaillierterer Kommentar zu Teds Antwort sowie Code / Daten. Python / Pandas ist nicht mein erstes / bestes, aber ich fand das gut zu lesen:
Ich finde es eher wie
dplyr
Pfeifen unddata.table
verkettete Befehle. Um nicht zu sagen, dass sie besser sind, mir nur vertrauter. (Ich erkenne zweifellos die Macht und für viele die Präferenz, formalisiertedef
Funktionen für diese Art von Operationen zu verwenden. Dies ist nur eine Alternative, nicht unbedingt besser.)Ich habe Daten auf die gleiche Weise wie Ted generiert. Ich werde einen Startwert für die Reproduzierbarkeit hinzufügen.
quelle
Pandas >= 0.25.0
, benannte AggregationenSeit der Pandas-Version
0.25.0
oder höher entfernen wir uns von der wörterbuchbasierten Aggregation und Umbenennung und gehen zu benannten Aggregationen über, die a akzeptierentuple
. Jetzt können wir gleichzeitig einen informativeren Spaltennamen zusammenfassen und umbenennen:Beispiel :
Bewerben Sie sich
GroupBy.agg
mit benannter Aggregation:quelle
Neu in Version 0.25.0.
Um die spaltenspezifische Aggregation mit Kontrolle über die Namen der Ausgabespalten zu unterstützen, akzeptiert pandas die spezielle Syntax in GroupBy.agg () , die als "benannte Aggregation" bezeichnet wird
pandas.NamedAgg ist nur ein benanntes Tupel. Auch einfache Tupel sind erlaubt.
Zusätzliche Schlüsselwortargumente werden nicht an die Aggregationsfunktionen übergeben. Nur Paare von (column, aggfunc) sollten als ** kwargs übergeben werden. Wenn Ihre Aggregationsfunktionen zusätzliche Argumente erfordern, wenden Sie diese teilweise mit functools.partial () an.
Die benannte Aggregation gilt auch für Seriengruppen-Aggregationen. In diesem Fall gibt es keine Spaltenauswahl, daher sind die Werte nur die Funktionen.
quelle
Teds Antwort ist erstaunlich. Ich habe letztendlich eine kleinere Version davon verwendet, falls jemand interessiert ist. Nützlich, wenn Sie nach einer Aggregation suchen, die von Werten aus mehreren Spalten abhängt:
Erstellen Sie einen Datenrahmen
Gruppieren und Aggregieren mit Apply (unter Verwendung mehrerer Spalten)
Gruppieren und Aggregieren mit Aggregat (unter Verwendung mehrerer Spalten)
Ich mag diesen Ansatz, da ich immer noch Aggregat verwenden kann. Vielleicht lassen mich die Leute wissen, warum eine Anwendung erforderlich ist, um bei Aggregationen für Gruppen auf mehrere Spalten zuzugreifen.
Es scheint jetzt offensichtlich, aber solange Sie die interessierende Spalte nicht direkt nach dem Gruppieren auswählen , haben Sie innerhalb Ihrer Aggregationsfunktion Zugriff auf alle Spalten des Datenrahmens.
Nur Zugriff auf die ausgewählte Spalte
Zugriff auf alle Spalten, da die Auswahl immerhin die Magie ist
oder ähnlich
Ich hoffe das hilft.
quelle