Temukan nilai minimum dalam bingkai data Pandas dan tambahkan label pada kolom baru
Perbaikan apa yang dapat saya lakukan pada kode python pandas saya agar lebih efisien? Untuk kasus saya, saya memiliki kerangka data ini
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]})
Yang memberikan hasil ini:
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
Yang perlu saya capai di sini adalah memperbarui bidang di bawah kolom Label ke MAIN untuk nilai aturan terendah yang terkait dengan setiap ID Aturan yang diterapkan ke ID dan Nama Orang. Oleh karena itu, hasilnya perlu terlihat seperti ini:
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
Ini adalah kode yang saya tulis untuk mencapai ini:
In [4]:
df['Label'] = np.where(
df['RuleNumber'] ==
df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].transform('min'),
"MAIN", df.Label)
Apakah ada cara yang lebih baik untuk memperbarui nilai di bawah kolom Label? Saya merasa seperti saya kasar memaksa saya dan ini mungkin bukan cara yang paling efisien untuk melakukan ini.
Saya menggunakan utas SO berikut untuk sampai pada hasil saya:
Ganti nilai kolom dalam groupby dan condition
Ganti nilai dalam grup berdasarkan pada beberapa kondisi
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
Menggunakan Panda untuk Menemukan Nilai Minimum dari Baris yang Dikelompokkan
Saran apa pun akan dihargai.
Terima kasih.
Jawaban
Sepertinya Anda dapat memfilter berdasarkan yang dikelompokkan idxmin
terlepas dari urutan yang diurutkan dan memperbarui RuleNumber
berdasarkan itu. Anda dapat menggunakan loc
, np.where
, mask
, atau where
sebagai berikut:
df.loc[df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].idxmin(), 'Label'] = 'MAIN'
ATAU dengan np.where
saat Anda mencoba:
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
Menggunakan mask
atau kebalikannya where
juga akan berfungsi:
df['Label'] = (df['Label'].mask((df.index == df.groupby(['PersonID', 'Name', 'RuleID'])
['RuleNumber'].transform('idxmin')), 'MAIN'))
ATAU
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'
Gunakan duplicated
di PersonID:
df.loc[~df['PersonID'].duplicated(),'Label'] = 'MAIN'
print(df)
Keluaran:
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