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

Dec 18 2020

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

1 DavidErickson Dec 18 2020 at 03:14

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'))
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

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