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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:07:35