如何对DataFrame分组、应用自定义函数并避免索引重复
更高效的解决方法:直接迭代分组并合并
你说得对,先生成多层索引再删除确实有点冗余。这里有两个更高效的方案,能避免不必要的索引操作:
方案1:迭代分组后直接pd.concat(推荐)
跳过groupby.apply自动生成索引的逻辑,直接遍历每个分组,处理完后合并结果:
import pandas as pd def sandwich(df): return pd.concat([df[:1], df, df[-1:]]) data = [[1, 1, 1, 0], [1, 2, 1, 1], [1, 2, 2, 2], [2, 1, 1, 3]] df = pd.DataFrame(data, columns=["idx 1", "idx 2", "idx 3", "value"]) # 遍历分组并合并处理后的结果 result = pd.concat([sandwich(group) for _, group in df.groupby(["idx 1", "idx 2"])])
输出结果就是你想要的扁平化DataFrame,不需要额外的索引清理步骤:
idx 1 idx 2 idx 3 value 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 1 1 2 1 1 1 1 2 1 1 2 1 2 2 2 2 1 2 2 2 3 2 1 1 3 3 2 1 1 3 3 2 1 1 3
这个方法的优势是完全避免了groupby.apply生成的多层索引,直接得到最终结构,在处理大数据集时性能会更优。
方案2:使用droplevel移除分组索引(轻量替代)
如果你更习惯用groupby.apply,可以用droplevel精准移除上层的分组索引,比reset_index(drop=True)更简洁(只删除分组生成的索引层,不影响原行索引):
result = df.groupby(["idx 1", "idx 2"]).apply(sandwich).droplevel([0, 1])
不过这个方法本质还是先生成索引再删除,效率略低于方案1,但比reset_index的操作更精准。
为什么原来的方法会出现重复?
groupby.apply默认会把分组键(idx 1和idx 2)作为多层索引的上层添加到结果中,同时原DataFrame的分组键列会被完整保留,所以才会出现"分组键既在索引里又在列里"的重复情况。而方案1直接绕过了这个索引生成逻辑,自然不会有这个问题。
内容的提问来源于stack exchange,提问作者edd313
相关产品推荐
相关产品推荐

