Tìm giá trị tối thiểu trong khung dữ liệu Pandas và thêm nhãn trên cột mới
Tôi có thể thực hiện những cải tiến nào đối với mã pandas python của mình để làm cho nó hoạt động hiệu quả hơn? Đối với trường hợp của tôi, tôi có khung dữ liệu này
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]})
Điều này mang lại kết quả:
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
Những gì tôi cần hoàn thành ở đây là cập nhật các trường trong cột Nhãn thành CHÍNH để có giá trị quy tắc thấp nhất được liên kết với mỗi ID quy tắc được áp dụng cho ID và Tên người. Do đó, kết quả cần có dạng như sau:
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
Đây là mã mà tôi đã viết để thực hiện điều này:
In [4]:
df['Label'] = np.where(
df['RuleNumber'] ==
df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].transform('min'),
"MAIN", df.Label)
Có cách nào tốt hơn để cập nhật các giá trị trong cột Nhãn không? Tôi cảm thấy như mình vũ phu buộc phải vượt qua và đây có thể không phải là cách hiệu quả nhất để làm điều này.
Tôi đã sử dụng các chuỗi SO sau để đi đến kết quả của mình:
Thay thế các giá trị cột trong một nhóm và điều kiện
Thay thế các giá trị trong một nhóm dựa trên nhiều điều kiện
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
Sử dụng gấu trúc để tìm giá trị tối thiểu của các hàng được nhóm
Lời khuyên nào sẽ được đánh giá cao.
Cảm ơn bạn.
Trả lời
Có vẻ như bạn có thể lọc theo nhóm được nhóm idxminbất kể thứ tự được sắp xếp và cập nhật RuleNumberdựa trên đó. Bạn có thể sử dụng loc, np.where, mask, hay wherenhư sau:
df.loc[df.groupby(['PersonID', 'Name', 'RuleID'])['RuleNumber'].idxmin(), 'Label'] = 'MAIN'
HOẶC với np.wherenhư bạn đã cố gắng:
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
Sử dụng maskhoặc nghịch đảo của nó wherecũng sẽ hoạt động:
df['Label'] = (df['Label'].mask((df.index == df.groupby(['PersonID', 'Name', 'RuleID'])
['RuleNumber'].transform('idxmin')), 'MAIN'))
HOẶC LÀ
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'
Sử dụng duplicatedtrên PersonID:
df.loc[~df['PersonID'].duplicated(),'Label'] = 'MAIN'
print(df)
Đầu ra:
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