Pandas 데이터 프레임에서 최소값을 찾고 새 열에 레이블을 추가합니다.

Dec 18 2020

python pandas 코드를 더 효율적으로 만들기 위해 어떤 개선을 할 수 있습니까? 제 경우에는이 데이터 프레임이 있습니다.

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]})

결과는 다음과 같습니다.

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

여기서 수행해야하는 것은 개인 ID 및 이름에 적용되는 각 규칙 ID와 연관된 가장 낮은 규칙 값에 대해 레이블 열 아래의 필드를 MAIN으로 업데이트하는 것입니다. 따라서 결과는 다음과 같아야합니다.

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

이 작업을 수행하기 위해 작성한 코드는 다음과 같습니다.

In [4]:

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

레이블 열 아래의 값을 업데이트하는 더 좋은 방법이 있습니까? 나는 내가 내 길을 강요하는 것처럼 느껴지며 이것이 가장 효율적인 방법이 아닐 수도 있습니다.

내 결과에 도달하기 위해 다음 SO 스레드를 사용했습니다.

groupby 및 조건 내에서 열 값 바꾸기

여러 조건에 따라 groupby 내의 값 바꾸기

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

Pandas를 사용하여 그룹화 된 행의 최소값 찾기

조언을 주시면 감사하겠습니다.

감사합니다.

답변

1 DavidErickson Dec 18 2020 at 03:14

idxmin정렬 순서에 관계없이 그룹별로 필터링하고이를 RuleNumber기반으로 업데이트 할 수있는 것 같습니다 . 당신이 사용할 수있는 loc, np.where, mask, 또는 where다음과 같이 :

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

또는 np.where시도한대로 :

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

mask또는 그 반대를 사용하면 다음 과 같이 where작동합니다.

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

또는

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

duplicatedPersonID에 사용 :

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

산출:

   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