如何基于两列分组去重,为col2生成col1组内统一排名列
问题描述
现有如下DataFrame:
import pandas as pd df = pd.DataFrame({'col1': ['A', 'A', 'A', 'A', 'B', 'C', 'C'], 'col2': ['a1', 'a1', 'a2', 'a2', 'b1', 'c1', 'c2']}) print(df)
输出:
col1 col2 0 A a1 1 A a1 2 A a2 3 A a2 4 B b1 5 C c1 6 C c2
需求:新增一列col3,用于标识col2在每个col1分组内的排名,同一col1分组中相同的col2值需对应相同的排名。
尝试了以下三段代码,均未得到正确结果:
df['col3_1'] = df.groupby(['col1', 'col2']).cumcount() + 1 df['col3_2'] = df.groupby(['col1'])['col2'].cumcount() + 1 df['col3_3'] = df.groupby(['col1', 'col2']).ngroup() + 1 print(df)
输出:
col1 col2 col3_1 col3_2 col3_3 0 A a1 1 1 1 1 A a1 2 2 1 2 A a2 1 3 2 3 A a2 2 4 2 4 B b1 1 1 3 5 C c1 1 1 4 6 C c2 1 2 5
注:col2的实际值无固定格式规律。
预期输出:
col1 col2 col3 0 A a1 1 1 A a1 1 2 A a2 2 3 A a2 2 4 B b1 1 5 C c1 1 6 C c2 2
解决方案
方法1:使用groupby + rank(method='dense')
rank方法的method='dense'参数会生成连续的排名,相同值获得相同排名且排名不会跳过数字,正好匹配需求:
df['col3'] = df.groupby('col1')['col2'].rank(method='dense', ascending=True).astype(int)
方法2:使用factorize结合transform
factorize会将分组内的唯一值映射为连续整数(从0开始),通过transform将映射结果应用到原DataFrame每一行,最后加1调整为从1开始的排名:
df['col3'] = df.groupby('col1')['col2'].transform(lambda x: pd.factorize(x)[0] + 1)
原代码错误原因说明
col3_1:按col1+col2分组后用cumcount,是统计每个子分组内的行序号,同一col2值会生成递增数字,不符合“相同值同排名”要求col3_2:按col1分组后对col2用cumcount,是统计分组内每行的顺序号,不管值是否重复,因此逐个递增col3_3:ngroup是给全局所有col1+col2组合分配唯一编号,不是分组内的排名,编号会跨分组连续递增
运行上述任一正确方法后,均可得到预期输出。
内容的提问来源于stack exchange,提问作者VERBOSE
相关产品推荐
相关产品推荐

