如何高效移除Pandas DataFrame中跨列值重复的行?
解决方案
要解决这个问题,核心思路是将每行的元素标准化为相同顺序的序列,这样就能用常规的去重方法识别出那些元素集合相同但列分布不同的行。下面是几种高效的实现方式:
方法一:每行元素排序后去重(最直观高效)
我们可以对DataFrame的每一行进行排序,生成一个用于判断重复的依据,然后保留每个唯一组的第一行:
import pandas as pd # 构造示例DataFrame df = pd.DataFrame(columns=['a','b','c','d'], index=['1','2','3']) df.loc['1'] = pd.Series({'a':'x','b':'y','c':'e','d':'f'}) df.loc['2'] = pd.Series({'a':'e','b':'f','c':'x','d':'y'}) df.loc['3'] = pd.Series({'a':'w','b':'v','c':'s','d':'t'}) # 关键步骤:对每行元素排序,转成元组作为去重key(列表不可哈希,元组可以) sorted_rows = df.apply(lambda row: tuple(sorted(row)), axis=1) # 保留第一个出现的唯一行,过滤掉后续重复行 df_new = df[~sorted_rows.duplicated(keep='first')] print(df_new)
运行后输出符合预期:
a b c d 1 x y e f 3 w v s t
细节解释:
df.apply(lambda row: tuple(sorted(row)), axis=1):遍历每一行(axis=1)对元素排序,转成元组后,行1和行2的结果会统一为('e', 'f', 'x', 'y'),以此标记为重复组。~sorted_rows.duplicated(keep='first'):duplicated(keep='first')会把重复组中除第一个行外的其他行标记为True,用~取反后就能筛选出所有唯一组的首行。
方法二:用groupby实现(适合扩展操作)
如果后续需要对重复组做更多处理(比如统计、合并),可以用groupby分组后取首行:
# 生成排序后的辅助列 df['sorted_key'] = df.apply(lambda row: tuple(sorted(row)), axis=1) # 按key分组,取每组第一行,再删除辅助列 df_new = df.groupby('sorted_key', as_index=False).first().drop('sorted_key', axis=1) # 恢复原索引(按需操作) df_new.index = ['1', '3'] print(df_new)
这个方法和方法一效果一致,优势是如果你的数据是数值型,还可以在groupby后直接做均值、求和等聚合操作。
大数据量优化方案
如果你的DataFrame行数特别多(百万级以上),用numpy的底层排序会比pandas.apply更快:
import numpy as np # 用numpy对每行元素排序,速度远快于lambda循环 sorted_np = np.sort(df.values, axis=1) # 转成元组序列作为去重key sorted_rows = [tuple(row) for row in sorted_np] # 筛选唯一行 df_new = df[~pd.Series(sorted_rows).duplicated(keep='first')]
numpy的排序是C语言实现的底层优化,能大幅提升处理速度。
内容的提问来源于stack exchange,提问作者maxtenzin
相关产品推荐
相关产品推荐

