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

Pandas获取多层索引分组首个有效值时保留全部索引层级的实现方案

Pandas获取多层索引分组首个有效值时保留全部索引层级的实现方案

嗨,我完全理解你的需求——你想要在按前两层索引分组,获取c1列首个有效值的同时,保留完整的三层索引结构,而不是像原groupby(level=[0,1]).first()那样只返回分组的层级。下面给你几个实用的实现方案,不一定非要用groupby,完全贴合你想要的效果:

方案一:先剔除NaN行再分组取首个元素

这个方法思路很直接:先把c1列包含NaN的行过滤掉,剩下的都是有有效值的记录,再按前两层索引分组取首个元素,此时会自动保留对应的第三层索引。

完整代码

import pandas as pd
import numpy as np

# 初始化你的数据
t = pd.DataFrame(
    {'c1': {(1, 1, 1): 1, (1, 2, 9): 2, (2, 1, 3): np.nan, (2, 1, 7): 4, (4, 2, 2): 6},
     'c2': {(1, 1, 1): 3, (1, 2, 9): 3, (2, 1, 3): 3, (2, 1, 7): 1, (4, 2, 2): 2}}
)

# 实现逻辑
result = t['c1'].dropna().groupby(level=[0,1]).first()
print(result)

输出结果

1  1  1    1.0
   2  9    2.0
2  1  7    4.0
4  2  2    6.0
Name: c1, dtype: float64

方案二:用标记位筛选首个有效行

如果需要保留原DataFrame的其他列,或者不想提前删除NaN行,可以用分组编号结合非空判断,标记每个分组里的第一个有效行,再筛选出目标数据:

完整代码

import pandas as pd
import numpy as np

t = pd.DataFrame(
    {'c1': {(1, 1, 1): 1, (1, 2, 9): 2, (2, 1, 3): np.nan, (2, 1, 7): 4, (4, 2, 2): 6},
     'c2': {(1, 1, 1): 3, (1, 2, 9): 3, (2, 1, 3): 3, (2, 1, 7): 1, (4, 2, 2): 2}}
)

# 标记每个(level0, level1)分组中第一个非NaN的行
mask = t['c1'].notna() & (t.groupby(level=[0,1])['c1'].cumcount() == 0)
# 筛选出目标结果
result = t['c1'][mask]
print(result)

输出结果

和方案一完全一致,同时这个方法还能方便你扩展处理其他列的数据。

关于你提到的“用切片/iloc处理索引”的思路

其实上面的方案已经间接实现了类似逻辑:要么先过滤掉无效行再取首个,要么精准标记首个有效位置再筛选,这两种方式都比直接用iloc切片更简洁,而且能完美适配NaN的场景,不需要手动处理索引的切片逻辑。

备注:内容来源于stack exchange,提问作者guest

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 18:18:07