Найдите минимальное значение в кадре данных Pandas и добавьте метку в новый столбец
Какие улучшения я могу внести в свой код 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
Что мне нужно здесь сделать, так это обновить поля в столбце Label до 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:
Заменить значения столбцов в группе по и условию
Заменить значения в группе на основе нескольких условий
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 для поиска минимальных значений сгруппированных строк
Любой совет будет принят во внимание.
Спасибо.
Ответы
Кажется, что вы можете фильтровать по группировке 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'))
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'
Использовать duplicated
на PersonID:
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