Suchen Sie den Mindestwert in einem Pandas-Datenrahmen und fügen Sie einer neuen Spalte eine Bezeichnung hinzu

Dec 18 2020

Welche Verbesserungen kann ich an meinem Python-Pandas-Code vornehmen, um ihn effizienter zu gestalten? Für meinen Fall habe ich diesen Datenrahmen

In [1]: df = pd.DataFrame({'PersonID': [1, 1, 1, 2, 2, 2, 3, 3, 3],
                           'Name': ["Jan", "Jan", "Jan", "Don", "Don", "Don", "Joe", "Joe", "Joe"],
                           'Label': ["REL", "REL", "REL", "REL", "REL", "REL", "REL", "REL", "REL"],
                           'RuleID': [55, 55, 55, 3, 3, 3, 10, 10, 10],
                           'RuleNumber': [3, 4, 5, 1, 2, 3, 234, 567, 999]})

Welches ergibt dieses Ergebnis:

In [2]: df
Out[2]: 
   PersonID Name Label  RuleID  RuleNumber
0         1  Jan   REL      55          3
1         1  Jan   REL      55          4
2         1  Jan   REL      55          5
3         2  Don   REL       3          1
4         2  Don   REL       3          2
5         2  Don   REL       3          3
6         3  Joe   REL      10        234
7         3  Joe   REL      10        567
8         3  Joe   REL      10        999

Was ich hier tun muss, ist, die Felder in der Spalte Beschriftung auf MAIN zu aktualisieren, um den niedrigsten Regelwert zu erhalten, der jeder Regel-ID zugeordnet ist, die auf eine Personen-ID und einen Namen angewendet wird. Daher müssen die Ergebnisse folgendermaßen aussehen:

In [3]: df
Out[3]:
   PersonID Name Label  RuleID  RuleNumber
0         1  Jan  MAIN      55           3
1         1  Jan   REL      55           4
2         1  Jan   REL      55           5
3         2  Don  MAIN       3           1
4         2  Don   REL       3           2
5         2  Don   REL       3           3
6         3  Joe  MAIN      10         234
7         3  Joe   REL      10         567
8         3  Joe   REL      10         999

Dies ist der Code, den ich geschrieben habe, um dies zu erreichen:

In [4]:

df['Label'] = np.where(
        df['RuleNumber'] ==
        df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].transform('min'),
        "MAIN", df.Label)

Gibt es eine bessere Möglichkeit, die Werte in der Spalte Beschriftung zu aktualisieren? Ich habe das Gefühl, dass ich mich brutal durchzwinge, und dies ist möglicherweise nicht der effizienteste Weg, dies zu tun.

Ich habe die folgenden SO-Threads verwendet, um zu meinem Ergebnis zu gelangen:

Ersetzen Sie Spaltenwerte innerhalb einer Gruppe durch und Bedingung

Ersetzen Sie Werte innerhalb einer Gruppe durch, basierend auf mehreren Bedingungen

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.idxmin.html

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.transform.html

Verwenden von Pandas zum Ermitteln von Mindestwerten für gruppierte Zeilen

Jeder Rat wäre dankbar.

Dankeschön.

Antworten

1 DavidErickson Dec 18 2020 at 03:14

Es scheint, als könnten Sie idxminunabhängig von der sortierten Reihenfolge nach der Gruppe filtern und darauf RuleNumberbasierend aktualisieren . Sie können verwendet werden loc, np.where, mask, oder wherewie folgt:

df.loc[df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].idxmin(), 'Label'] = 'MAIN'

ODER mit, np.wherewie Sie es versucht haben:

df['Label'] = (np.where((df.index == df.groupby(['PersonID', 'Name', 'RuleID'])
                         ['RuleNumber'].transform('idxmin')), 'MAIN', 'REL'))
df
Out[1]: 
   PersonID Name Label  RuleID  RuleNumber
0         1  Jan  MAIN      55           3
1         1  Jan   REL      55           4
2         1  Jan   REL      55           5
3         2  Don  MAIN       3           1
4         2  Don   REL       3           2
5         2  Don   REL       3           3
6         3  Joe  MAIN      10         234
7         3  Joe   REL      10         567
8         3  Joe   REL      10         999

Die Verwendung maskoder deren Umkehrung wherewürde auch funktionieren:

df['Label'] = (df['Label'].mask((df.index == df.groupby(['PersonID', 'Name', 'RuleID'])
                         ['RuleNumber'].transform('idxmin')), 'MAIN'))

ODER

df['Label'] = (df['Label'].where((df.index != df.groupby(['PersonID', 'Name', 'RuleID'])
                         ['RuleNumber'].transform('idxmin')), 'MAIN'))
1 Scared Dec 18 2020 at 03:25
import pandas as pd

df = pd.DataFrame({'PersonID': [1, 1, 1, 2, 2, 2, 3, 3, 3],
'Name': ["Jan", "Jan", "Jan", "Don", "Don", "Don", "Joe", "Joe", "Joe"],
'Label': ["REL", "REL", "REL", "REL", "REL", "REL", "REL", "REL", "REL"],
'RuleID': [55, 55, 55, 3, 3, 3, 10, 10, 10],
'RuleNumber': [3, 4, 5, 1, 2, 3, 234, 567, 999]})

df.loc[df.groupby('Name')['RuleNumber'].idxmin()[:], 'Label'] = 'MAIN'
ScottBoston Dec 18 2020 at 03:45

Verwendung duplicatedauf PersonID:

df.loc[~df['PersonID'].duplicated(),'Label'] = 'MAIN'
print(df)

Ausgabe:

   PersonID Name Label  RuleID  RuleNumber
0         1  Jan  MAIN      55           3
1         1  Jan   REL      55           4
2         1  Jan   REL      55           5
3         2  Don  MAIN       3           1
4         2  Don   REL       3           2
5         2  Don   REL       3           3
6         3  Joe  MAIN      10         234
7         3  Joe   REL      10         567
8         3  Joe   REL      10         999