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

如何用Pandas移除复合键重复行并保留分散非缺失值?

预期结果

我有如下格式的数据表:
输入图片描述
希望将其转换为如下格式:
输入图片描述

问题描述

ID和Event #字段构成复合键,代表表中的唯一条目。
条目可能存在两次或多次重复,但部分行值分散在重复行中,且无法确定有效数据位于重复行的首行、末行还是中间行。
我希望移除重复条目,同时保留所有已填充的行值,无论其分布在哪些重复行中。

如何用Pandas实现这一需求?

查阅相关内容后,我认为需要使用groupby和fillna或ffill/bfill方法,但作为Pandas新手,我不清楚如何在以下条件下实现:

  • 行通过复合键区分
  • 存在超过1条重复行的情况
  • 有效数据分散在重复行的多个字段中
  • 无法确定有效数据位于重复行的首行、末行还是中间行

以下是示例DataFrame:

df = pd.DataFrame([['ABC111',   1,  '1/1/23 12:00:00',  None,               '1/1/23 13:30:00',  None], 
    ['ABC111',      2,  '1/2/23 00:00:00',  None,               '1/2/23 13:30:00',  None], 
    ['ABC111',      3,  '1/3/23 00:00:00',  None,               '1/3/23 13:30:00',  None], 
    ['ABC112',      1,  '1/1/23 00:00:00',  None,               '1/1/23 13:30:00',  None], 
    ['ABC112',      2,  '1/2/23 00:00:00',  'Test Value A',     None,               None], 
    ['ABC112',      2,  '1/2/23 00:00:00',  'Test Value A',     None,               None], 
    ['ABC112',      2,  None,               None,               '1/2/23 13:30:00',  'Test Value B'], 
    ['ABC113',      1,  '1/1/23 00:00:00',  None,               '1/1/23 13:30:00',  None], 
    ['ABC113',      2,  '1/2/23 00:00:00',  None,               '1/2/23 13:30:00',  None], 
    ['ABC113',      3,  None,               None,               '1/3/23 13:30:00',  'Test Value B'], 
    ['ABC113',      3,  '1/3/23 00:00:00',  'Test Value A',     None,               None], 
    ['ABC114',      1,  '1/1/23 00:00:00',  'Test Value A',     None,               None], 
    ['ABC114',      1,  None,               None,               '1/1/23 13:30:00',  'Test Value B'], 
    ['ABC114',      1,  None,               None,               '1/1/23 13:30:00',  'Test Value B'], 
    ['ABC114',      1,  None,               None,               '1/1/23 13:30:00',  'Test Value B'], 
    ['ABC114',      1,  None,               None,               '1/1/23 13:30:00',  'Test Value B'], 
    ['ABC114',      2,  '1/2/23 00:00:00',  None,               '1/2/23 13:30:00',  None], 
    ['ABC114',      3,  '1/3/23 00:00:00',  None,               '1/3/23 13:30:00',  None]],
    columns=['ID', 'Event #', 'Start Date', 'Start Value', 'End Date', 'End Value'])

解决方案

你可以通过分组+聚合非空值的方式实现需求,核心逻辑是按复合键ID和Event #分组,将每组内分散在不同行的有效数据合并到一行,同时移除重复条目。以下是几种可行方法:

方法1:分组后聚合取第一个非空值

该方法直接对每组的每个字段提取第一个非空值,确保保留有效数据,是最稳妥的方案:

# 按复合键分组,对每个列取第一个非空值;若列全为空则保留None
result = df.groupby(['ID', 'Event #'], as_index=False).agg(
    lambda x: x.dropna().iloc[0] if not x.dropna().empty else None
)

方法2:分组填充缺失值后去重

先对每组进行前向+后向填充,让同一组内所有行都补全有效数据,再去重保留每组唯一一行:

# 分组后用前向+后向填充补全缺失值
filled_df = df.groupby(['ID', 'Event #']).apply(lambda x: x.ffill().bfill())
# 去重保留每组唯一条目
result = filled_df.drop_duplicates(['ID', 'Event #'])

方法3:利用first聚合(适用于非空值唯一场景)

如果同一组内每个字段的非空值都是唯一的,直接用first聚合就能快速得到结果,它会取每组内第一个出现的非空值:

result = df.groupby(['ID', 'Event #'], as_index=False).first()

以上三种方法都能满足你的需求,可根据实际数据场景选择:方法1通用性最强;方法2适合需要保留原表部分行结构的情况;方法3最简单高效。

内容的提问来源于Stack Exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 02:57:33