Pandas:按组为唯一值按首次出现顺序分配序号的问题
问题解决:按首次出现顺序生成稠密排名
问题重现
原始DataFrame:
import pandas as pd df = pd.DataFrame({ 'ID':['27637', '27637', '27637', '27637', '89283', '89283', '89283', '89283'], 'Country':['UK', 'Poland', 'Poland', 'Poland', 'China', 'China', 'India', 'India']})
执行以下代码添加排名列后:
df['Dense_Rank'] = df.groupby('ID')['Country'].rank(method='dense')
发现ID=27637的分组中,UK首次出现却被标记为2.0,Poland被标记为1.0,不符合预期;而ID=89283的分组结果正常。预期结果如下:
| ID | Country | Dense_Rank | Expected_Result |
|---|---|---|---|
| 27637 | UK | 2.0 | 1.0 |
| 27637 | Poland | 1.0 | 2.0 |
| 27637 | Poland | 1.0 | 2.0 |
| 27637 | Poland | 1.0 | 2.0 |
| 89283 | China | 1.0 | 1.0 |
| 89283 | China | 1.0 | 1.0 |
| 89283 | India | 2.0 | 2.0 |
| 89283 | India | 2.0 | 2.0 |
原因分析
rank(method='dense')默认按字符串字母顺序对分组内的Country排序后分配排名。在ID=27637的分组中,"Poland"首字母P在"UK"的U之前,所以排名为1;ID=89283的分组中"China"的C在"India"的I之前,结果符合预期。但你需要的是按元素首次出现顺序生成排名。
解决方案
方法1:使用groupby+factorize
factorize会按元素首次出现的顺序生成编码,加1后即可得到符合要求的稠密排名:
df['Expected_Result'] = df.groupby('ID')['Country'].transform(lambda x: pd.factorize(x)[0] + 1)
执行后结果完全符合预期:
ID Country Dense_Rank Expected_Result 0 27637 UK 2.0 1.0 1 27637 Poland 1.0 2.0 2 27637 Poland 1.0 2.0 3 27637 Poland 1.0 2.0 4 89283 China 1.0 1.0 5 89283 China 1.0 1.0 6 89283 India 2.0 2.0 7 89283 India 2.0 2.0
方法2:利用rank的key参数
指定按首次出现顺序作为排序依据:
df['Expected_Result'] = df.groupby('ID')['Country'].rank(method='dense', key=lambda x: x.factorize()[0])
内容的提问来源于stack exchange,提问作者the_tc
相关产品推荐
相关产品推荐

