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

Pandas为何丢弃分组索引?如何保留分组索引?

问题分析与解决

测试数据准备

df_temp = {
   'id': [0,0,0,1,1,1],
   'time' : [1,2,3,1,2,3],
   'values': [3,6,1,4,0,-1]
}
df_temp = pd.DataFrame(df_temp)
df_temp = df_temp.set_index('time')

两个对比案例

案例1

df_temp.groupby('id')[['values']].apply(lambda _df: _df)

案例2

df_temp.groupby('id')[['values']].apply(lambda _df: _df[:-1])

差异原因

Pandas的groupby.apply()内置了自动简化机制:当lambda返回的分组DataFrame和原分组的结构(行数、索引、列数)完全一致时,Pandas会自动“扁平化”结果——它认为既然每个分组的结构都和原分组没区别,就没必要保留分组索引,直接合并成和原数据结构类似的输出;而如果返回的DataFrame和原分组结构不一致(比如案例2中每组少了最后一行),Pandas会保留分组索引并将其作为外层索引,形成(id, time)的多层索引,用来明确区分不同组的结果。

修改案例1的方法

要在不删减每组数据的前提下保留分组索引,有三种实用方法:

方法1:修改分组返回的索引结构

让lambda返回的DataFrame使用多层索引,把分组的id作为外层索引,这样即使行数不变,结构和原分组也不一样,Pandas就不会扁平化结果:

df_temp.groupby('id')[['values']].apply(
    lambda _df: _df.rename(index=lambda t: (_df.name, t))
)

方法2:手动添加分组标识列

给每个分组的DataFrame添加id列,改变原分组的列结构,触发Pandas保留分组索引:

df_temp.groupby('id')[['values']].apply(
    lambda _df: _df.assign(id=_df.name)
)

如果之后需要把id转为索引,再执行df.set_index(['id', 'time'])即可。

方法3:直接用pd.concat拼接分组结果

这种方法更直观,直接将每个分组按id作为键拼接成多层索引的DataFrame:

pd.concat(
    [group for _, group in df_temp.groupby('id')[['values']]],
    keys=df_temp['id'].unique(),
    names=['id', 'time']
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:20:39