499 Stimmen

Holen Sie sich die Zeile(n) mit dem maximalen Wert in Gruppen mithilfe von groupby

Wie finde ich alle Reihen in einem Pandas DataFrame, die den maximalen Wert für die count-Spalte haben, nachdem sie nach den ['Sp','Mt']-Spalten gruppiert wurden?

Beispiel 1: das folgende DataFrame:

   Sp   Mt Value   count
0  MM1  S1   a     **3**
1  MM1  S1   n       2
2  MM1  S3   cb    **5**
3  MM2  S3   mk    **8**
4  MM2  S4   bg    **10**
5  MM2  S4   dgd     1
6  MM4  S2   rd      2
7  MM4  S2   cb      2
8  MM4  S2   uyi   **7**

Die erwartete Ausgabe besteht darin, die Zeilen zu erhalten, deren Zähler in jeder Gruppe maximal ist, wie folgt:

   Sp   Mt   Value  count
0  MM1  S1   a      **3**
2  MM1  S3   cb     **5**
3  MM2  S3   mk     **8**
4  MM2  S4   bg     **10** 
8  MM4  S2   uyi    **7**

Beispiel 2:

   Sp   Mt   Value  count
4  MM2  S4   bg     10
5  MM2  S4   dgd    1
6  MM4  S2   rd     2
7  MM4  S2   cb     8
8  MM4  S2   uyi    8

Die erwartete Ausgabe:

   Sp   Mt   Value  count
4  MM2  S4   bg     10
7  MM4  S2   cb     8
8  MM4  S2   uyi    8

6voto

Surya Punkte 9736

Erkenntnis, dass "anwenden" "nlargest" auf groupby Objekt genauso gut funktioniert:

Zusätzlicher Vorteil - kann auch top n Werte abrufen, wenn erforderlich:

In [85]: import pandas as pd

In [86]: df = pd.DataFrame({
    ...: 'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
    ...: 'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
    ...: 'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
    ...: 'count' : [3,2,5,8,10,1,2,2,7]
    ...: })

## wenden nlargest(1) an, um den Maximalwert von df zu finden, und nlargest(n) gibt die Top-n-Werte für df:
In [87]: df.groupby(["sp", "mt"]).apply(lambda x: x.nlargest(1, "count")).reset_index(drop=True)
Out[87]:
   count  mt   sp  val
0      3  S1  MM1    a
1      5  S3  MM1   cb
2      8  S3  MM2   mk
3     10  S4  MM2   bg
4      7  S2  MM4  uyi

4voto

nbertagnolli Punkte 398

Wenn Sie Ihr DataFrame sortieren, wird diese Reihenfolge in der Gruppierung beibehalten. Sie können dann einfach das erste oder letzte Element auswählen und den Index zurücksetzen.

df = pd.DataFrame({
    'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
    'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
    'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
    'count' : [3,2,5,8,10,1,2,2,7]
})

df.sort_values("count", ascending=False).groupby(["sp", "mt"]).first().reset_index()

3voto

Jon Punkte 712

Viele von ihnen sind großartige Antworten, aber um die Skalierbarkeit zu zeigen, zeigen 2,8 Millionen Zeilen mit einer variierenden Anzahl von Duplikaten einige erstaunliche Unterschiede. Am schnellsten für meine Daten war das Sortieren nach dann Löschen von Duplikaten (alle außer dem letzten nur marginal schneller als absteigend sortieren und alle außer dem ersten löschen)

  1. Aufsteigend sortieren, letzte Duplikate behalten (2,22 s)
  2. Absteigend sortieren, erste Duplikate behalten (2,32 s)
  3. Transformieren mit Max innerhalb der loc-Funktion (3,73 s)
  4. Max speichern mit IDX und dann im zweiten Schritt mit loc auswählen (3,84 s)
  5. Groupby mit Tail (8,98 s)
  6. IDMax mit Groupby und dann im zweiten Schritt Loc auswählen (95,39 s)
  7. IDMax mit Groupby innerhalb der Loc-Auswahl (95,74 s)
  8. NLargest(1) und dann im zweiten Schritt mit iloc auswählen (> 35000 s) - lief auch nach einer Übernachtung nicht zu Ende
  9. NLargest(1) innerhalb von iloc auswählen (> 35000 s) - lief nach einer Übernachtung nicht zu Ende

Wie man sieht, ist Sortieren um 1/3 schneller als Transformieren und 75% schneller als Groupby. Alles andere ist bis zu 40-mal langsamer. In kleinen Datensätzen spielt dies möglicherweise keine große Rolle, aber wie Sie sehen können, kann dies große Datensätze erheblich beeinträchtigen.

2voto

George Liu Punkte 3581
df = pd.DataFrame({
'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
'count' : [3,2,5,8,10,1,2,2,7]
})

df.groupby(['sp', 'mt']).apply(lambda grp: grp.nlargest(1, 'count'))

-1voto

upuil Punkte 67

df.loc[df.groupby('mt')['count'].idxmax()]

Wenn der df Index nicht eindeutig ist, benötigen Sie möglicherweise zuerst diesen Schritt df.reset_index(inplace=True).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X