如何使用combine_first方法合并含重复索引的DataFrame行?
使用combine_first合并重复索引的DataFrame行
问题背景
给定如下代码创建的带有重复索引的DataFrame:
import pandas as pd # 创建含重复索引值的示例DataFrame data = {'A': [1, 2, None, 4, 5], 'B': [None, None, 3, None, 4]} df = pd.DataFrame(data, index=[1, 2, 2, 3, 3])
需要通过combine_first方法将所有重复索引的行合并为单行,实现类似df.groupby(df.index).agg(...)的逻辑——对分组逐行应用combine_first直至合并为单行。
期望两种输出结果:
- 保留第一个非空值:
{'A': [1, 2, 4], 'B': [None, 3, 4]}
- 保留最后一个非空值:
{'A': [1, 2, 5], 'B': [None, 3, 4]}
解决方案
1. 保留第一个非空值(从前向后合并)
通过groupby分组后,自定义聚合函数对每组行从前到后依次调用combine_first,优先保留先出现的非空值:
def combine_forward(group): merged_row = group.iloc[0] for row in group.iloc[1:]: merged_row = merged_row.combine_first(row) return merged_row result_forward = df.groupby(df.index).apply(combine_forward) print(result_forward.to_dict('list'))
输出符合预期:
{'A': [1.0, 2.0, 4.0], 'B': [None, 3.0, 4.0]}
2. 保留最后一个非空值(从后向前合并)
若要保留每组中最后出现的非空值,只需反转分组内的行顺序,再执行合并逻辑:
def combine_backward(group): merged_row = group.iloc[-1] for row in reversed(group.iloc[:-1]): merged_row = row.combine_first(merged_row) return merged_row result_backward = df.groupby(df.index).apply(combine_backward) print(result_backward.to_dict('list'))
输出符合预期:
{'A': [1.0, 2.0, 5.0], 'B': [None, 3.0, 4.0]}
简化实现(利用functools.reduce)
借助functools.reduce可以简化聚合逻辑,让代码更紧凑:
- 保留第一个非空值:
from functools import reduce result_forward = df.groupby(df.index).apply(lambda g: reduce(lambda x, y: x.combine_first(y), g))
- 保留最后一个非空值:
result_backward = df.groupby(df.index).apply(lambda g: reduce(lambda x, y: y.combine_first(x), g))
内容的提问来源于stack exchange,提问作者LucaM
相关产品推荐
相关产品推荐

