Pandas多索引DataFrame实现更新+新增合并的技术问询
实现多索引DataFrame的Upsert(更新+新增)合并
我明白你要的是那种「已有数据就更新,没有就新增」的合并效果——也就是数据库里常说的upsert操作,pandas里确实没有直接的函数一步到位,但我们可以用concat+groupby的组合来实现,完美解决你遇到的那些问题。
解决方案代码
结合你的测试数据,具体实现如下:
import pandas as pd import numpy as np zones = ['A', 'B', 'C'] # 你的原始测试数据 dates0 = pd.date_range('20180101', '20180102', freq='D') dates1 = pd.date_range('20180103', '20180104', freq='D') idx00 = pd.MultiIndex.from_product(iterables=[dates0, [zones[0]]], names= ['UTC', 'zone']) df00 = pd.DataFrame(index=idx00, columns=['a', 'b'], data=[[1, 2], [3, 4]]) idx01 = pd.MultiIndex.from_product(iterables=[dates1, [zones[0]]], names=['UTC', 'zone']) df01 = pd.DataFrame(index=idx01, columns=['a', 'b'], data=[[5, 6], [7, 8]]) idx10 = pd.MultiIndex.from_product(iterables=[dates0, [zones[1]]], names=['UTC', 'zone']) df10 = pd.DataFrame(index=idx10, columns=['b', 'c'], data=np.random.rand(2, 2)) idx11 = pd.MultiIndex.from_product(iterables=[dates1, [zones[1]]], names=['UTC', 'zone']) df11 = pd.DataFrame(index=idx11, columns=['b', 'c'], data=np.random.rand(2, 2)) df00b = pd.DataFrame(index=idx00, columns=['a', 'b'], data=[[10, 20], [30, 40]]) # 核心逻辑:合并所有DataFrame后按多索引分组取最新值 dfs_to_merge = [df00, df01, df10, df11, df00b] df_final = pd.concat(dfs_to_merge).groupby(level=['UTC', 'zone']).last() df_final.sort_index(inplace=True) print(df_final)
效果验证
运行后你会得到符合预期的结果:
- 原A区的旧数据被
df00b更新为a=10/30、b=20/40 - 成功新增B区的所有行和
c列 - 没有重复行,所有列名保持原始名称,缺失值自动用
NaN填充
为什么这个方法能解决你的问题?
针对你之前遇到的各个方法的痛点,这个方案逐一解决:
- 替代
append():不会产生重复行,同一索引的行被合并为一行,保留列表中最后出现的最新值 - 替代
merge():不会修改列名,所有列都维持原始命名,无需处理后缀 - 替代
update():通过concat自动新增不存在的行和列,再通过groupby整合数据 - 替代
join():无需手动定义后缀,所有列和索引都被自动整合
小技巧
如果你的数据有优先级顺序(比如某些DataFrame的更新权重更高),只需调整dfs_to_merge列表的顺序——越靠后的DataFrame,其数据优先级越高,会覆盖前面的旧数据。
内容的提问来源于stack exchange,提问作者Theo
相关产品推荐
相关产品推荐

