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
相关产品推荐
相关产品推荐

