如何在pandas DataFrame中为重复分组添加唯一标识标签
问题描述
现有如下DataFrame:
df = pd.DataFrame({'id': ['A', 'A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D'], 'value1': ['1', '2', '3', '4', '1', '2', '1', '2', '3', '4', '1', '2', '3'], 'value2': ['1', '2', '3', '4', '1', '2', '1', '2', '3', '4', '1', '2', '3'], 'value3': ['1', '2', '3', '4', '1', '2', '1', '2', '3', '4', '1', '2', '3'], })
需求:新增名为duplicated的列,为value列匹配的不同重复分组分配唯一标签,首个重复组标记为1,后续依次递增。
已知背景:
- 实际场景有20+列,包含NaN值
- 已将原始长表通过
pivot_table转为宽表,匹配重复时排除id列,当前筛选重复行的代码如下:
df = df_long.pivot_table(index="Y",columns="Z",values="value").reset_index() subset = [c for c in df.columns if not c=="id"] df = df.loc[df.duplicated(subset=subset,keep=False)].copy()
- 使用pandas 0.22版本,执行如下
groupby代码无分组返回:
for i, group in df.groupby(subset): print(group)
解决方案
1. 重复分组唯一标记实现(兼容pandas 0.22、支持NaN值)
直接使用pd.factorize对需要判重的列组合编码即可,无需依赖groupby,代码如下:
subset = [c for c in df.columns if c != "id"] # 将每行的判重列转为元组后编码,+1实现从1开始标记 df["duplicated"] = pd.factorize(df[subset].apply(tuple, axis=1))[0] + 1
如果你的数据是未转宽的长表,需要按id整组判重,使用如下代码:
subset = [c for c in df.columns if c != "id"] # 按id分组后将整组值转为可哈希的元组,再编码 group_hash = df.groupby("id")[subset].apply(lambda x: tuple(x.values.flatten())) df = df.merge(group_hash.reset_index(name="group_hash"), on="id") df["duplicated"] = pd.factorize(df["group_hash"])[0] + 1
2. groupby无分组返回问题解决
pandas 0.22版本groupby默认会丢弃包含NaN值的分组,且不支持dropna=False参数,可先将NaN填充为全局唯一的占位符后再分组:
# 填充NaN为不会在业务数据中出现的占位符 df_fill = df[subset].fillna("__INTERNAL_NAN_PLACEHOLDER__") for i, group in df.groupby(list(df_fill.columns)): print(group)
内容的提问来源于stack exchange,提问作者Rockbar
相关产品推荐
相关产品推荐

