如何基于两个条件删除DataFrame分组中不需要的行?
高效处理DataFrame分组过滤需求
输入数据
import pandas as pd df = pd.DataFrame({'col1': ['A', 'A', 'B', 'C', 'D', 'D', 'D', 'E', 'E'], 'col2': ['x1', 'x2', 'x1', 'x1', 'x1', 'x2', 'x3', 'x1', 'x2'], 'col3': ['', 'mssg1', 'mssg2', '', 'mssg3', '', 'mssg4', '', '']})
需求说明
按col1分组后执行如下过滤规则:
- 若分组内有多行,且存在
col3非空的行:仅保留col3非空的行 - 若分组内所有行
col3都为空:保留分组内所有行 - 若分组只有一行:直接保留该行
原始代码的问题
你当前的apply逐组处理方式在大数据集上效率极低,因为apply本质是循环操作,无法利用pandas的矢量化优化。另外,replace('', None)再fillna('')的操作也存在冗余。
优化解决方案
用矢量化操作替代逐组循环,全程利用pandas的内置函数实现高效计算:
# 1. 标记col3是否非空(空字符串视为空) df['col3_non_empty'] = df['col3'] != '' # 2. 计算每个col1分组的两个关键指标:分组大小、是否存在非空col3 group_info = df.groupby('col1').agg( group_size=('col1', 'size'), has_non_empty=('col3_non_empty', 'any') ).reset_index() # 3. 将分组指标合并回原DataFrame df_with_group = df.merge(group_info, on='col1') # 4. 生成过滤条件 filter_condition = ( # 分组只有一行,直接保留 (df_with_group['group_size'] == 1) # 分组全为空,保留所有行 | (~df_with_group['has_non_empty']) # 分组有多行且存在非空,保留当前行col3非空的 | (df_with_group['col3_non_empty']) ) # 5. 过滤并清理临时列 final = df_with_group[filter_condition].drop(columns=['col3_non_empty', 'group_size', 'has_non_empty'])
验证结果
执行后得到的final输出与期望完全一致:
col1 col2 col3 1 A x2 mssg1 2 B x1 mssg2 3 C x1 4 D x1 mssg3 6 D x3 mssg4 7 E x1 8 E x2
效率说明
这种方案全程使用pandas的矢量化聚合、合并操作,避免了逐组循环,在大数据集上的运行效率比apply版本提升数倍甚至数十倍,同时逻辑清晰无遗漏,完全覆盖所有规则场景。
内容的提问来源于stack exchange,提问作者VERBOSE
相关产品推荐
相关产品推荐

