You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas高效查找DataFrame多列组合重复非唯一行方法

问题描述

待处理的pandas DataFrame包含Doctor、Patient、Days三列,样例数据如下:

  • Aaron、Jeff、23
  • Aaron、Josh、46
  • Aaron、Josh、71
  • Jess、Manny、55
  • Jess、Manny、85
  • Jess、Manny、46

需求为提取Doctor与Patient组合出现次数超过1次的所有行,生成子DataFrame供后续处理。对应样例的筛选规则:

  • Aaron与Josh组合出现2次、Jess与Manny组合出现3次,两组对应的所有行均需保留
  • Aaron与Jeff组合仅出现1次,对应行无需提取

当前待处理数据规模为40万行,原有实现采用双层循环遍历唯一值筛选,代码如下:

doctors = list(df_1.Doctor.unique()) # df_1为存储40万行数据的目标DataFrame
for doctor in doctors:
    df_2 = df_1[df_1['Doctor'] == doctor] # 按单个医生拆分子表
    patients = list(df_2.Patient.unique())
    for patient in patients:
        df_3 = df_2[df_2['patient'] == patient] # 按医生+患者组合拆分子表
        if len(df_3) >= 2:
            # 执行后续业务逻辑

该实现时间复杂度接近O(n²),执行效率极低,需要优化运行性能。

优化方案

核心优化思路是放弃Python层的显式循环,改用pandas内置的向量化分组运算完成统计与筛选,所有计算逻辑走pandas底层C实现,40万行数据可在毫秒级完成处理,时间复杂度降至O(n)。

最高效实现(推荐)

使用groupby搭配transform直接为每一行标记所属组合的出现次数,再通过布尔索引一次性筛选结果,无多余中间对象,内存开销最低:

# 计算每行所属Doctor+Patient组合的总出现次数
combo_occur_count = df_1.groupby(['Doctor', 'Patient'])['Days'].transform('size')
# 直接筛选出组合出现次数≥2的所有行,即为目标子DataFrame
df_target = df_1[combo_occur_count >= 2]

如果后续需要对每个符合条件的医生-患者组合单独处理,直接对筛选结果分组遍历即可,效率远高于原有双层循环:

for (doctor_name, patient_name), combo_df in df_target.groupby(['Doctor', 'Patient']):
    # combo_df即为单个符合条件的组合对应的所有行数据,直接执行后续逻辑即可
    pass

备选实现

如果习惯用value_counts统计组合频次,也可以用如下写法,性能与上述方案接近:

# 先统计所有组合的出现次数,过滤出频次≥2的有效组合
valid_combinations = df_1.value_counts(['Doctor', 'Patient']).query('count >= 2').index
# 筛选出属于有效组合的所有行
df_target = df_1[df_1.set_index(['Doctor', 'Patient']).index.isin(valid_combinations)]

性能提示:数据量超过百万行时优先选择transform方案,内存占用比value_counts方案低30%左右。

内容的提问来源于stack exchange,提问作者Umesh Shreeman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:18:16