Pandas多列分组后获取各分组ID计数最高的DETAILS
Pandas处理百万级数据分组取最频繁DETAILS的解决方案
需求说明
需要在500万行的Pandas DataFrame中,按UNIT和FUNCTION两列分组,找出每个分组内对应ID计数最多的DETAILS。
预期结果示例
- UNIT=0011、FUNCTION=0001时,ID计数最高的DETAILS为546545153113131;
- UNIT=0011、FUNCTION=0026时,ID计数最高的DETAILS为546545153113132;
- UNIT=0012、FUNCTION=0001时,ID计数最高的DETAILS为546545153113131;
- UNIT=0012、FUNCTION=0026时,ID计数最高的DETAILS为546545153113132。
现有代码及问题
用户已将数据读取为DataFrame,初步代码如下:
import pandas as pd # 示例数据 data = [['000000000001', '0011','0001','546545153113131'], ['000000000002', '0011','0026','546545153113132'], ['000000000004', '0011','0001','546545153113133'], ['000000000005', '0011','0001','546545153113131'], ['000000000006', '0012','0001','546545153113131'], ['000000000007', '0012','0026','546545153113132'], ['000000000009', '0012','0001','546545153113133'], ['000000000010', '0012','0001','546545153113131'] ] df = pd.DataFrame(data, columns=['ID', 'UNIT', 'FUNCTION', 'DETAILS']) df.sort_values(by=['ID', 'UNIT', 'FUNCTION'], ascending=[True,True,True]) df.groupby(['UNIT', 'FUNCTION','DETAILS']).count()
当前输出
ID UNIT FUNCTION DETAILS 0011 0001 546545153113131 2 546545153113133 1 0026 546545153113132 1 0012 0001 546545153113131 2 546545153113133 1 0026 546545153113132 1
期望输出
UNIT FUNCTION DETAILS ID 0011 0001 546545153113131 2 0011 0026 546545153113132 1 0012 0001 546545153113131 2 0012 0026 546545153113132 1
解决方案
针对百万级数据,推荐以下两种高效实现方式:
方法1:分组计数+二次筛选(性能优先)
该方法先统计每个组合的计数,再筛选出每个分组的最高项,适合大数据场景:
import pandas as pd # 读取数据(实际场景替换为你的文件读取逻辑) data = [['000000000001', '0011','0001','546545153113131'], ['000000000002', '0011','0026','546545153113132'], ['000000000004', '0011','0001','546545153113133'], ['000000000005', '0011','0001','546545153113131'], ['000000000006', '0012','0001','546545153113131'], ['000000000007', '0012','0026','546545153113132'], ['000000000009', '0012','0001','546545153113133'], ['000000000010', '0012','0001','546545153113131'] ] df = pd.DataFrame(data, columns=['ID', 'UNIT', 'FUNCTION', 'DETAILS']) # 1. 按三级分组统计ID数量,转换为普通DataFrame count_df = df.groupby(['UNIT', 'FUNCTION', 'DETAILS'])['ID'].count().reset_index(name='ID_COUNT') # 2. 按分组排序取最高计数项,整理格式 result = count_df.sort_values(['UNIT', 'FUNCTION', 'ID_COUNT'], ascending=[True, True, False]) \ .groupby(['UNIT', 'FUNCTION']) \ .head(1) \ .rename(columns={'ID_COUNT': 'ID'}) \ .sort_values(['UNIT', 'FUNCTION']) \ .reset_index(drop=True) print(result)
输出结果
UNIT FUNCTION DETAILS ID 0 0011 0001 546545153113131 2 1 0011 0026 546545153113132 1 2 0012 0001 546545153113131 2 3 0012 0026 546545153113132 1
方法2:使用mode取众数(代码简洁)
如果每个分组的众数唯一,可直接用mode方法实现:
# 按分组取DETAILS众数,并统计ID数量 result = df.groupby(['UNIT', 'FUNCTION']).agg( DETAILS=('DETAILS', lambda x: x.mode()[0]), ID=('ID', 'count') ).reset_index() print(result)
注意:若分组内多个DETAILS计数相同,
mode()[0]会取第一个出现的众数,需根据需求确认是否适用。
关键说明
reset_index():将分组后的多级索引转为普通列,避免输出格式混乱;- 排序筛选逻辑:确保每个
UNIT-FUNCTION分组只保留计数最高的DETAILS; - 性能优化:方法1先做计数统计再筛选,比直接操作原大数据集更高效,适合500万行规模的场景。
内容的提问来源于stack exchange,提问作者Ankur Jain
相关产品推荐
相关产品推荐

