如何为Pandas中重复分组键基于列值和序列分配唯一标签
问题描述
现有如下Pandas DataFrame:
import itertools import operator import pandas as pd d = {'idx' : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'names' : ['a', 'b', 'c', 'd', 'dd', 'eqq', 'n', 'oo', 'rt', 'xyz', 'yy'], 'grp_key' : [4, 4, 5, 5, 5, 7, 8, 8, 8, 4, 4] } df = pd.DataFrame.from_dict(d)
希望基于grp_key列进行分组,已通过itertools.groupby实现分组:
G = [list(group) for key, group in itertools.groupby(df.grp_key.values)] print(G) # 输出:[[4, 4], [5, 5, 5], [7], [8, 8, 8], [4, 4]]
或结合idx与grp_key分组:
gpr_idx = list(zip(df.grp_key.values, df.idx.values)) G = [list(group) for key, group in itertools.groupby(gpr_idx, operator.itemgetter(0))] print(G) # 输出:[[(4, 0), (4, 1)], [(5, 2), (5, 3), (5, 4)], [(7, 5)], [(8, 6), (8, 7), (8, 8)], [(4, 9), (4, 10)]]
但无法实现为重复的分组键分配唯一标签,期望输出格式如下:
idx names grp_key unique_tag 0 0 a 4 4_G1 1 1 b 4 4_G1 2 2 c 5 5_G1 3 3 d 5 5_G1 4 4 dd 5 5_G1 5 5 eqq 7 7_G1 6 6 n 8 8_G1 7 7 oo 8 8_G1 8 8 rt 8 8_G1 9 9 xyz 4 4_G2 10 10 yy 4 4_G2
请问如何用更Pythonic或Pandas原生的方式实现该需求?
解决方案
可以利用Pandas的shift()和cumsum()标记连续同值组,结合分组排序生成唯一标签,全程用Pandas原生方法实现:
分步实现代码
# 标记连续组的分界:当前行grp_key与上一行不同则记为1,否则0,累加后得到全局组编号 df['group_id'] = (df['grp_key'] != df['grp_key'].shift()).cumsum() # 按grp_key分组,为每个grp_key下的连续组分配自增序号 df['tag_seq'] = df.groupby('grp_key')['group_id'].rank(method='dense').astype(int) # 拼接生成unique_tag df['unique_tag'] = df['grp_key'].astype(str) + '_G' + df['tag_seq'].astype(str) # 删除中间辅助列(可选) df = df.drop(['group_id', 'tag_seq'], axis=1) print(df)
输出结果
idx names grp_key unique_tag 0 0 a 4 4_G1 1 1 b 4 4_G1 2 2 c 5 5_G1 3 3 d 5 5_G1 4 4 dd 5 5_G1 5 5 eqq 7 7_G1 6 6 n 8 8_G1 7 7 oo 8 8_G1 8 8 rt 8 8_G1 9 9 xyz 4 4_G2 10 10 yy 4 4_G2
简洁写法(省略辅助列)
df['unique_tag'] = ( df['grp_key'].astype(str) + '_G' + df.groupby('grp_key') .apply(lambda x: (x['grp_key'] != x['grp_key'].shift()).cumsum()) .astype(str) )
内容的提问来源于stack exchange,提问作者Bharat Sharma
相关产品推荐
相关产品推荐

