在 Pandas 数据框中找到最小值并在新列上添加标签
Posted
技术标签:
【中文标题】在 Pandas 数据框中找到最小值并在新列上添加标签【英文标题】:Find the minimum value in a Pandas dataframe and add a label on new column 【发布时间】:2021-03-28 13:04:03 【问题描述】:我可以对我的 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
我需要在这里完成的是将标签列下的字段更新为 MAIN,以获取与应用于人员 ID 和姓名的每个规则 ID 关联的最低规则值。因此,结果需要如下所示:
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 线程得出我的结果:
Replace column values within a groupby and condition
Replace values within a groupby based on multiple conditions
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
Using Pandas to Find Minimum Values of Grouped Rows
任何建议将不胜感激。
谢谢。
【问题讨论】:
【参考方案1】:您似乎可以按分组的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'))
【讨论】:
【参考方案2】: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'
【讨论】:
最好将索引值直接传递给.loc
。它有效,但无需搜索.isin
是否存在索引值。您基本上可以使用df.loc[indexes, 'Label'] = 'MAIN'
来删除使用isin
进行搜索的冗余步骤。【参考方案3】:
在 PersonID 上使用 duplicated
:
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
【讨论】:
以上是关于在 Pandas 数据框中找到最小值并在新列上添加标签的主要内容,如果未能解决你的问题,请参考以下文章
如果 ID 存在于其他数据框中,则 Python Pandas 数据框在新列中添加“1”
Pandas - 使用 PostCoder 在每一行中查找纬度和经度,然后在新列中返回 Postcode