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

基于两个MultiIndex DataFrame创建大型Series的高效实现

高效匹配MultiIndex DataFrame生成Series的解决方案

问题背景

现有两个带多层索引(MultiIndex)的DataFrame:

  • df1的索引index1定义:
    pd.MultiIndex.from_tuples([('1','c'),('1','d'),('2','c'),('2','d')], names=['level1','level2'])
    
  • df2的索引index2定义:
    pd.MultiIndex.from_tuples([(1,'1','c'), (2,'1','c'),(3,'1','d'),(4,'2','d'),(6,'2','d')],names=['level0','level1','level2'])
    

需求是:基于df1指定列的level1+level2匹配关系,生成一个以df2的level0值为索引的pd.Series。

示例数据与期望输出

示例df1构造代码:

import pandas as pd
index1 = pd.MultiIndex.from_tuples([('1','c'),('1','d'),('2','c'),('2','d')], names=['level1','level2'])
df1 = pd.DataFrame({'A':['foo','bar','baz','qux'],'B':['foo1','bar1','baz1','qux1']}, index=index1)

期望输出Series:

pd.Series(['foo1','foo1', 'bar1', 'qux1','qux1'], index=[1,2,3,4,6])

当前痛点

原实现通过遍历df2的索引逐个匹配,代码如下:

column_name = 'B'
result = [df1[column_name].loc[indx[1:]][0] for indx in df2.index] 
new_indx = [i[0] for i in df2.index]
result = pd.Series(result, index=new_indx)

但df2数据量极大时,遍历操作会导致运行速度极慢,需要无需遍历df2的高效方案(可接受遍历较小的df1)。


高效解决方案

方法1:索引重置+合并(直观易读)

利用pandas的合并操作批量匹配,避免逐行遍历:

column_name = 'B'

# 提取df1的level1、level2与目标列的映射关系,转为普通DataFrame
mapping_df = df1[column_name].reset_index()

# 提取df2的level0、level1、level2信息
df2_info = df2.reset_index()[['level0', 'level1', 'level2']]

# 基于level1和level2合并,生成结果Series
merged = df2_info.merge(mapping_df, on=['level1', 'level2'], how='left')
result_series = merged.set_index('level0')[column_name]

方法2:直接利用索引元组批量匹配(性能最优)

从df2的MultiIndex中提取level1和level2组成元组序列,直接用df1的索引进行批量映射:

column_name = 'B'

# 从df2索引中提取level1和level2,组成匹配用的元组列表
match_keys = list(zip(
    df2.index.get_level_values('level1'),
    df2.index.get_level_values('level2')
))

# 直接通过元组序列从df1中取值,再设置索引为df2的level0
result_series = pd.Series(
    df1[column_name].loc[match_keys].values,
    index=df2.index.get_level_values('level0')
)

方法3:遍历小df1批量赋值(符合需求中“可遍历df1”)

如果df1数据量很小,可遍历其每个level1+level2组合,批量更新结果Series:

column_name = 'B'

# 初始化结果Series,索引为df2的level0
result_series = pd.Series(index=df2.index.get_level_values('level0'))

# 遍历df1的每个索引项和对应值
for (l1, l2), val in df1[column_name].items():
    # 筛选df2中当前level1+level2对应的所有level0
    mask = (df2.index.get_level_values('level1') == l1) & \
           (df2.index.get_level_values('level2') == l2)
    target_level0 = df2.index.get_level_values('level0')[mask]
    # 批量赋值
    result_series.loc[target_level0] = val

结果验证

以上三种方法生成的result_series均与期望输出一致:

level0
1    foo1
2    foo1
3    bar1
4    qux1
6    qux1
Name: B, dtype: object

内容的提问来源于stack exchange,提问作者Merimace

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:18:22