基于标识匹配更新/追加Pandas DataFrame的代码实现求助
在Pandas中基于标识值更新/追加DataFrame的高效方法
我来帮你解决这个问题,你的思路是对的,但其实有更高效的Pandas原生方法,比逐行循环要好很多。先看看怎么修改你的循环代码满足需求,再给你推荐更优的向量化方案:
一、修改你的循环代码(适合小数据场景)
你的循环逻辑没问题,只是替换对应行的部分可以这样实现,另外注意append已经被Pandas官方弃用了,建议用pd.concat替代:
import pandas as pd # 示例数据 DF1 = pd.DataFrame({'Col1': [1,2,3], 'Col2': [11,22,33], 'Col3': ['aa','bb','cc']}) DF2 = pd.DataFrame({'Col1': [1,2,4], 'Col2': ['01','02','04'], 'Col3': ['xx','yy','zz']}) for idx in DF1.index: df1_row = DF1.iloc[idx] # 找到DF2中Col1匹配的行索引 match_indices = DF2[DF2['Col1'] == df1_row['Col1']].index if not match_indices.empty: # 替换对应行的所有字段 DF2.loc[match_indices] = df1_row.values else: # 追加行到DF2,用concat替代弃用的append DF2 = pd.concat([DF2, df1_row.to_frame().T], ignore_index=True) print(DF2)
运行后就能得到你想要的结果,但要注意:这种逐行循环的方式在DataFrame数据量大的时候(比如几万行以上)会非常慢,因为Pandas的设计初衷是支持向量化操作,逐行处理会极大浪费性能,所以更推荐下面的方案。
二、高效的向量化方案(推荐)
这里有两种更高效的方法,都是利用Pandas原生的向量化操作,性能比循环好几个数量级:
方法1:合并后去重
核心思路是把作为更新源的DF1放在前面,和DF2合并后按Col1去重,保留第一次出现的行(也就是DF1的行,优先更新),还可以调整行顺序和原DF2一致:
import pandas as pd DF1 = pd.DataFrame({'Col1': [1,2,3], 'Col2': [11,22,33], 'Col3': ['aa','bb','cc']}) DF2 = pd.DataFrame({'Col1': [1,2,4], 'Col2': ['01','02','04'], 'Col3': ['xx','yy','zz']}) # 合并DF1和DF2,DF1在前确保去重时优先保留更新值 combined = pd.concat([DF1, DF2], ignore_index=True) # 按Col1去重,保留第一个出现的行 updated_DF2 = combined.drop_duplicates(subset='Col1', keep='first') # 可选:保持原DF2的行顺序,再追加新增的行 original_order = DF2['Col1'].tolist() new_entries = DF1[~DF1['Col1'].isin(original_order)]['Col1'].tolist() final_order = original_order + new_entries updated_DF2 = updated_DF2.set_index('Col1').loc[final_order].reset_index() print(updated_DF2)
方法2:使用update函数+追加新行
先将两个DataFrame的Col1设为索引,用update更新已有行,再追加DF1中不存在的行,逻辑更清晰:
import pandas as pd DF1 = pd.DataFrame({'Col1': [1,2,3], 'Col2': [11,22,33], 'Col3': ['aa','bb','cc']}) DF2 = pd.DataFrame({'Col1': [1,2,4], 'Col2': ['01','02','04'], 'Col3': ['xx','yy','zz']}) # 设置Col1为索引,方便匹配更新 df1_indexed = DF1.set_index('Col1') df2_indexed = DF2.set_index('Col1') # 更新DF2中已存在的行(仅更新DF1有值的字段,这里我们是全字段更新,刚好适用) df2_indexed.update(df1_indexed) # 获取DF1中不在DF2里的行,追加到更新后的DF2 new_rows = df1_indexed[~df1_indexed.index.isin(df2_indexed.index)] updated_DF2 = pd.concat([df2_indexed, new_rows]).reset_index() print(updated_DF2)
这两种方法都能快速得到你想要的结果,而且数据量越大,性能优势越明显。
内容的提问来源于stack exchange,提问作者Mayank Shekhar
相关产品推荐
相关产品推荐

