不修改行序,按指定列合并行并保留各列首个非空值
解决DataFrame按identity合并并保留首个非空值且不改变行序的问题
需求说明
- 禁止修改或排序行序列(此前使用
groupby按id分组会改变/排序行序) - 所有DataFrame均包含参考列
identity,需按数据重要性顺序拼接(重要性高的在前) - 合并相同
identity值的行:合并后每行的各列需取该组内首个非空值(涵盖numpy.nan、空字符串、CSV导入的无值情况),若所有行均无值则列留空
基础代码
import pandas as pd import numpy as np new_df_one = pd.DataFrame({ 'identity':['1234','9999','1111'], 'column_a':['hhhh','aaaa',''], 'column_b':['hhhh',np.nan,np.nan], 'column_c':[np.nan,'aaaa',''], 'column_d':['hhhh','aaaa',''] }) new_df_two = pd.DataFrame({ 'identity':['1234','9999'], 'column_a':[np.nan,np.nan], 'column_b':[np.nan,np.nan], 'column_c':[np.nan,np.nan], 'column_d':['zzzz',np.nan] }) original_df = pd.DataFrame({ 'identity':['1234','1111'], 'column_a':[np.nan,'gggg'], 'column_b':[np.nan,'gggg'], 'column_c':['hhhh','gggg'], 'column_d':['hhhh','gggg'] }) concat_df = pd.concat([new_df_one, new_df_two, original_df], ignore_index=True)
此前尝试的问题
- Test 1:使用
agg(lambda x: ''.join(x))会将所有值拼接,不符合"取首个非空值"的要求 - Test 2:
groupby('id').first()存在两个问题:一是groupby默认会对分组键排序,破坏原行序;二是first()会直接取组内第一行的值,不会跳过空字符串/NaN去取后面的有效值
解决方案
- 统一空值表示:将空字符串转换为
np.nan,确保所有无值情况可以被统一处理 - 按
identity分组时设置sort=False,保留原数据中identity首次出现的顺序 - 自定义聚合函数,取每组内首个非空值;若全为空则留空
# 统一空值:将空字符串转为np.nan concat_df = concat_df.replace('', np.nan) # 按identity分组(不排序),取每组首个非空值 result_df = concat_df.groupby('identity', sort=False).agg( lambda x: x.dropna().iloc[0] if not x.dropna().empty else np.nan ).reset_index() # 可选:将np.nan转回空字符串,匹配预期结果的显示格式 result_df = result_df.replace(np.nan, '') print(result_df)
运行结果
identity column_a column_b column_c column_d 0 1234 hhhh hhhh hhhh hhhh 1 9999 aaaa aaaa aaaa 2 1111 gggg gggg gggg gggg
内容的提问来源于stack exchange,提问作者Digital Farmer
相关产品推荐
相关产品推荐

