Suchen Sie den Mindestwert in einem Pandas-Datenrahmen und fügen Sie einer neuen Spalte eine Bezeichnung hinzu
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
Es scheint, als könnten Sie idxmin
unabhängig von der sortierten Reihenfolge nach der Gruppe filtern und darauf RuleNumber
basierend aktualisieren . Sie können verwendet werden loc
, np.where
, mask
, oder where
wie folgt:
df.loc[df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].idxmin(), 'Label'] = 'MAIN'
ODER mit, np.where
wie 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 mask
oder deren Umkehrung where
wü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'))
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'
Verwendung duplicated
auf 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