Wir prüfen jede Bewertung auf unserer Website gründlich, mit dem Ziel, Ihnen immer die genauesten und aktuellsten Informationen zu zeigen.
Lösung:
Die zweite Hälfte der derzeit akzeptierten Antwort ist veraltet und hat zwei Verwerfungen. Erstens und am wichtigsten ist, dass Sie nicht mehr ein Wörterbuch von Wörterbüchern an die Funktion agg
groupby-Methode übergeben. Zweitens, verwenden Sie niemals .ix
.
Wenn Sie mit zwei getrennten Spalten gleichzeitig arbeiten möchten, empfehle ich die Verwendung der Methode apply
Methode, die implizit einen DataFrame an die angewandte Funktion übergibt. Verwenden wir einen ähnlichen DataFrame wie den von oben
df = pd.DataFrame(np.random.rand(4,4), columns=list('abcd'))
df['group'] = [0, 0, 1, 1]
df
a b c d group
0 0.418500 0.030955 0.874869 0.145641 0
1 0.446069 0.901153 0.095052 0.487040 0
2 0.843026 0.936169 0.926090 0.041722 1
3 0.635846 0.439175 0.828787 0.714123 1
Ein Wörterbuch, das von Spaltennamen auf Aggregationsfunktionen abgebildet wird, ist immer noch ein guter Weg, um eine Aggregation durchzuführen.
df.groupby('group').agg({'a':['sum', 'max'],
'b':'mean',
'c':'sum',
'd': lambda x: x.max() - x.min()})
a b c d
sum max mean sum
group
0 0.864569 0.446069 0.466054 0.969921 0.341399
1 1.478872 0.843026 0.687672 1.754877 0.672401
Wenn Sie den hässlichen Lambda-Spaltennamen nicht mögen, können Sie eine normale Funktion verwenden und der speziellen Funktion einen eigenen Namen geben __name__
Attribut einen benutzerdefinierten Namen geben, etwa so:
def max_min(x):
return x.max() - x.min()
max_min.__name__ = 'Max minus Min'
df.groupby('group').agg({'a':['sum', 'max'],
'b':'mean',
'c':'sum',
'd': max_min})
a b c d
sum max mean sum Max minus Min
group
0 0.864569 0.446069 0.466054 0.969921 0.341399
1 1.478872 0.843026 0.687672 1.754877 0.672401
Verwendung von apply
und der Rückgabe einer Serie
Wenn Sie nun mehrere Spalten haben, die miteinander interagieren müssen, können Sie nicht agg
verwenden, das implizit eine Reihe an die Aggregationsfunktion übergibt. Bei Verwendung von apply
wird die gesamte Gruppe als DataFrame an die Funktion übergeben.
Ich empfehle, eine einzige benutzerdefinierte Funktion zu erstellen, die eine Serie aller Aggregationen zurückgibt. Verwenden Sie den Index der Serie als Beschriftung für die neuen Spalten:
def f(x):
d = {}
d['a_sum'] = x['a'].sum()
d['a_max'] = x['a'].max()
d['b_mean'] = x['b'].mean()
d['c_d_prodsum'] = (x['c'] * x['d']).sum()
return pd.Series(d, index=['a_sum', 'a_max', 'b_mean', 'c_d_prodsum'])
df.groupby('group').apply(f)
a_sum a_max b_mean c_d_prodsum
group
0 0.864569 0.446069 0.466054 0.173711
1 1.478872 0.843026 0.687672 0.630494
Wenn Sie MultiIndexe lieben, können Sie immer noch eine Serie mit einem wie diesem zurückgeben:
def f_mi(x):
d = []
d.append(x['a'].sum())
d.append(x['a'].max())
d.append(x['b'].mean())
d.append((x['c'] * x['d']).sum())
return pd.Series(d, index=[['a', 'a', 'b', 'c_d'],
['sum', 'max', 'mean', 'prodsum']])
df.groupby('group').apply(f_mi)
a b c_d
sum max mean prodsum
group
0 0.864569 0.446069 0.466054 0.173711
1 1.478872 0.843026 0.687672 0.630494
Für den ersten Teil können Sie ein Diktat von Spaltennamen als Schlüssel und eine Liste von Funktionen für die Werte übergeben:
In [28]: df
Out[28]:
A B C D E GRP
0 0.395670 0.219560 0.600644 0.613445 0.242893 0
1 0.323911 0.464584 0.107215 0.204072 0.927325 0
2 0.321358 0.076037 0.166946 0.439661 0.914612 1
3 0.133466 0.447946 0.014815 0.130781 0.268290 1
In [26]: f = {'A':['sum','mean'], 'B':['prod']}
In [27]: df.groupby('GRP').agg(f)
Out[27]:
A B
sum mean prod
GRP
0 0.719580 0.359790 0.102004
1 0.454824 0.227412 0.034060
UPDATE 1:
Da die Aggregatfunktion mit Serien arbeitet, 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 ein kleiner Trick, um das Problem zu umgehen:
In [67]: f = {'A':['sum','mean'], 'B':['prod'], 'D': lambda g: df.loc[g.index].E.sum()}
In [69]: df.groupby('GRP').agg(f)
Out[69]:
A B D
sum mean prod
GRP
0 0.719580 0.359790 0.102004 1.170219
1 0.454824 0.227412 0.034060 1.182901
Hier besteht die resultierende Spalte "D" aus den summierten "E"-Werten.
UPDATE 2:
Hier ist eine Methode, die meiner Meinung nach alles tut, was Sie verlangen. Erstellen Sie zunächst eine benutzerdefinierte Lambda-Funktion. Im Folgenden verweist g auf die Gruppe. Beim Aggregieren wird g eine Serie sein. Übergabe g.index
an df.ix[]
wird die aktuelle Gruppe aus df ausgewählt. Dann prüfe ich, ob Spalte C kleiner als 0,5 ist. Die zurückgegebene boolesche Reihe wird an g[]
übergeben, der nur die Zeilen auswählt, die die Kriterien erfüllen.
In [95]: cust = lambda g: g[df.loc[g.index]['C'] < 0.5].sum()
In [96]: f = {'A':['sum','mean'], 'B':['prod'], 'D': {'my name': cust}}
In [97]: df.groupby('GRP').agg(f)
Out[97]:
A B D
sum mean prod my name
GRP
0 0.719580 0.359790 0.102004 0.204072
1 0.454824 0.227412 0.034060 0.570441
Pandas >= 0.25.0
, benannte Aggregationen
Seit der Pandas-Version 0.25.0
oder höher bewegen wir uns weg von der wörterbuchbasierten Aggregation und Umbenennung und bewegen uns hin zu benannten Aggregationen, die eine tuple
. Jetzt können wir gleichzeitig aggregieren und umbenennen, um einen informativeren Spaltennamen zu erhalten:
Beispiel:
df = pd.DataFrame(np.random.rand(4,4), columns=list('abcd'))
df['group'] = [0, 0, 1, 1]
a b c d group
0 0.521279 0.914988 0.054057 0.125668 0
1 0.426058 0.828890 0.784093 0.446211 0
2 0.363136 0.843751 0.184967 0.467351 1
3 0.241012 0.470053 0.358018 0.525032 1
anwenden. GroupBy.agg
mit benannter Aggregation:
df.groupby('group').agg(
a_sum=('a', 'sum'),
a_mean=('a', 'mean'),
b_mean=('b', 'mean'),
c_sum=('c', 'sum'),
d_range=('d', lambda x: x.max() - x.min())
)
a_sum a_mean b_mean c_sum d_range
group
0 0.947337 0.473668 0.871939 0.838150 0.320543
1 0.604149 0.302074 0.656902 0.542985 0.057681
Bewertungen und Kommentare
Wenn Sie ein Hindernis und die Fähigkeit haben, unser Schreiben zu verbessern, empfehlen wir Ihnen, eine Interpretation zu hinterlassen, und wir werden uns diese mit Interesse ansehen.