如何移除Pandas DataFrame同ID下互换列重复行并统计跨ID频次
解决Pandas中重复姓名对的去重与统计问题
嘿,作为Python/Pandas新手遇到这种问题太正常了,我来一步步帮你搞定这两个需求~
首先先把你的原始数据还原成Pandas DataFrame,方便后续操作:
import pandas as pd data = { 'id': [104, 104, 104, 236, 388, 388, 104, 236, 236], 'name_x': ['molly', 'james', 'sarah', 'molly', 'adam', 'johnny', 'adam', 'adam', 'pete'], 'name_y': ['james', 'molly', 'adam', 'adam', 'sarah', 'pete', 'sarah', 'james', 'johnny'] } df = pd.DataFrame(data)
需求1:移除同一id下重复的姓名对(不考虑顺序)
核心思路是:对每个id分组后,把每行的name_x和name_y按固定顺序排序,生成一个唯一的“姓名对键”,然后在每个id组内基于这个键去重,只保留第一次出现的行。
代码实现:
# 生成排序后的姓名对作为去重的唯一标识 df['sorted_names'] = df.apply(lambda row: tuple(sorted([row['name_x'], row['name_y']])), axis=1) # 按id和sorted_names分组,保留每组的第一行 df_deduplicated = df.groupby(['id', 'sorted_names']).first().reset_index(drop=True) # 删掉临时生成的sorted_names列,得到最终去重后的DataFrame df_deduplicated = df_deduplicated.drop('sorted_names', axis=1)
运行后,df_deduplicated就是你要的目标DataFrame,同一id下像molly-james和james-molly、sarah-adam和adam-sarah这类重复对都会被去掉。
需求2:统计姓名对在不同id下的出现次数及对应id列表
这里同样需要先把无序的姓名对转换成统一的标识,然后基于这个标识分组统计:
代码实现:
# 还是先生成排序后的姓名对作为分组依据 df['sorted_names'] = df.apply(lambda row: tuple(sorted([row['name_x'], row['name_y']])), axis=1) # 分组后统计不同id的数量、收集id列表,同时保留姓名对(这里取第一次出现的姓名顺序) result_df = df.groupby('sorted_names').agg( count=('id', 'nunique'), # 统计该姓名对出现过的不同id数量 ids=('id', list), # 收集所有出现过的id name_x=('name_x', 'first'), # 保留第一次出现的name_x name_y=('name_y', 'first') # 保留第一次出现的name_y ).reset_index(drop=True) # 调整列的顺序,和你给出的示例一致 result_df = result_df[['count', 'ids', 'name_x', 'name_y']]
如果你希望输出的name_x和name_y始终是按字母排序的(比如统一输出adam-sarah而不是sarah-adam),可以把最后两步替换成:
# 从排序后的姓名对中提取统一顺序的name_x和name_y result_df['name_x'] = result_df['sorted_names'].apply(lambda x: x[0]) result_df['name_y'] = result_df['sorted_names'].apply(lambda x: x[1]) # 调整列顺序并删除临时列 result_df = result_df[['count', 'ids', 'name_x', 'name_y']].drop('sorted_names', axis=1)
运行后就能得到和你示例几乎一致的统计结果啦~
内容的提问来源于stack exchange,提问作者ERS
相关产品推荐
相关产品推荐

