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

Pandas分组迭代中drop_duplicates未按预期工作的问题排查

问题分析与解决方法

问题背景

现有一个多列DataFrame,每行对应一条火车票数据,包含valid_from、valid_to日期以及列车、线路相关信息;其中route_key非唯一,涵盖票务提供商、起止点等信息。需求是:按route_key分组,将同一提供商同一路线的车票归为一组;每组按valid_from升序排序,过滤掉除valid_from、valid_to外所有列的重复项,最终得到无重复的车票合同数据。

当前代码在遍历分组迭代器时,drop_duplicates偶尔无法识别重复项,导致多余条目被保留;但单独通过get_group取出分组处理时,代码却能正常去重。

核心原因

  1. inplace=True的副作用:遍历分组时使用group.sort_values(..., inplace=True)会直接修改分组对象,而groupby迭代器返回的分组与原DataFrame存在浅拷贝引用关系,修改操作会打乱后续分组的数据源,导致drop_duplicates判断异常。
  2. 迭代过程中的对象引用混乱:手动遍历分组时,修改原分组对象会影响迭代器内部的状态,使得后续分组的处理基于被修改过的数据,进而出现去重失效的情况。

解决方法

方法1:避免inplace操作,使用副本处理

遍历分组时,生成排序后的副本而非直接修改原分组,确保每个分组都是独立的干净数据:

grouped_df = network_dfs[0].groupby('route_key')
list_dfs_grouped = []

for name, group in grouped_df:
    # 生成排序后的副本,不修改原分组对象
    sorted_group = group.sort_values('valid_from', ascending=True)
    dup_first = sorted_group.drop_duplicates(subset=my_col, keep="first")
    dup_last = sorted_group.drop_duplicates(subset=my_col, keep="last")
    
    # 用.values规避索引不匹配问题,确保赋值准确
    dup_first['valid_from'] = dup_last['valid_to'].values
    list_dfs_grouped.append(dup_first)

clean_df = pd.concat(list_dfs_grouped, axis=0, join='inner')

方法2:使用groupby.apply统一处理

用apply替代手动遍历,apply会自动为每个分组创建独立副本,避免引用混乱问题,代码更简洁:

def process_group(group):
    sorted_group = group.sort_values('valid_from', ascending=True)
    dup_first = sorted_group.drop_duplicates(subset=my_col, keep="first")
    dup_last = sorted_group.drop_duplicates(subset=my_col, keep="last")
    dup_first['valid_from'] = dup_last['valid_to'].values
    return dup_first

clean_df = network_dfs[0].groupby('route_key').apply(process_group).reset_index(drop=True)

额外注意事项

  • 确认my_col已包含除valid_from、valid_to外的所有目标列,避免因漏列导致重复项未被过滤。
  • 赋值valid_from时使用.values,可避免dup_first与dup_last索引不一致引发的NaN或赋值错误。

内容的提问来源于stack exchange,提问作者Moritz Backhaus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:40:11