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

如何将分组取TopN后的MultiIndex转换为多列DataFrame?

解决按分组取TopN值并转换为宽表的问题

咱们先明确你的需求:给定初始DataFrame,按A分组后提取每个分组中B出现次数最多的前2个值,最终转换成每个A对应两列(比如B_top1、B_top2)的宽表结构,同时要避免循环,还要兼容分组中B值不足2个的情况。

初始DataFrame

先把你的初始数据再明确下:

import pandas as pd

df = pd.DataFrame({
    'A': ['A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2'],
    'B': ['B1', 'B1', 'B2', 'B2', 'B3', 'B3', 'B4', 'B5', 'B6', 'B7', 'B7', 'B8', 'B8']
})

分析你当前代码的问题

你当前的代码先按A和B分组计数,再按A取Top2,得到的是带MultiIndex的Series:

df = df.groupby(['A', 'B'])['A'].count()
df = df.groupby(level=0).nlargest(2).reset_index(level=0, drop=True)

这个结果的索引是A和B,直接用reset_index(level=1)会变成两列,但没法直接拆成Top1和Top2的列;而unstack()默认是把B作为列,但这样列名是B的取值,不是我们要的B_top1、B_top2结构。

用原生方法实现目标结构

这里有两种简洁的原生方法可以实现,完全不需要循环,还能兼容分组内B值不足2个的情况:

方法一:结合value_counts、cumcount和pivot

# 按A分组统计B的出现次数,取每个组的Top2,重置索引
top_b = df.groupby('A')['B'].value_counts().head(2).reset_index(name='count')
# 给每个A分组内的TopN添加1、2的序号标记
top_b['rank'] = top_b.groupby('A').cumcount() + 1
# 转成宽表并重命名列
result = top_b.pivot(index='A', columns='rank', values='B').rename(columns={1: 'B_top1', 2: 'B_top2'})

方法二:更简洁的groupby+apply+unstack

# 对每个A分组,取B出现次数最多的前2个值的索引,再转成宽表
result = df.groupby('A')['B'].apply(lambda x: x.value_counts().head(2).index).unstack()
# 给列重命名为清晰的TopN格式
result.columns = [f'B_top{i+1}' for i in result.columns]

两种方法最终都会得到如下结果:

B_top1 B_top2
A                 
A1      B1     B2
A2      B7     B8

如果某个A分组内只有1个B值(比如假设A3的B只有B9),结果中B_top2会自动填充为NaN,完美兼容这种边缘情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:58:24