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

如何对Pandas分组后的多列同时应用自定义函数?

我来帮你理清楚这个问题,核心是groupby后对多列应用函数时,apply和agg的行为差异被你忽略了~

先看问题本质

当你对单列用groupby()['value1'].apply(get_most_common)时,apply会把每个分组的Series单独传给你的函数,刚好匹配get_most_common的输入要求。但当你选择多列[['value1','value2']]时,apply会把每个分组的整个子DataFrame传给函数,而不是按列拆分传入,这就导致你的函数处理的是整个子DataFrame的所有元素,而非每一列的元素,结果自然不符合预期。


正确解决方法:用agg()替代apply()

agg()(aggregate的缩写)专门用于分组后的列聚合操作,它会自动把每一列作为独立的Series传入你的自定义函数,完美匹配你的需求:

import pandas as pd
from collections import Counter

def get_most_common(srs):
    """返回列表中出现次数最多的值,多值并列时取Counter.most_common(1)的结果"""
    x = list(srs)
    my_counter = Counter(x)
    most_common_value = my_counter.most_common(1)[0][0]
    return most_common_value

# 初始化你的DataFrame
df = pd.DataFrame({'id':[1,1,1,1,1,2,2,2],'month':[1,1,2,2,2,1,2,2],'value1':[1,1,3,3,5,6,7,7], 'value2': [9,10,11,12,12,14,15,15], 'others': range(8)})

# 多列聚合的正确写法
result = df.groupby(['id','month'])[['value1','value2']].agg(get_most_common)
print(result)

运行后就能得到你想要的预期结果:

value1  value2
id month
1  1              1       9
   2              3      12
2  1              6      14
   2              7      15

为什么你之前的尝试都失败了?

我们逐个拆解原因:

  1. 直接用apply()处理多列:
    此时每个分组的子DataFrame会被整体传入get_most_common,比如第一个分组(id=1, month=1)的子DataFrame是两行5列的数据,你的函数会把所有元素转成列表[1,1,9,10,0,1],然后找这个混合列表的众数,完全偏离了你要的“按列取众数”的目标。

  2. 用transform():
    transform()的设计目的是把聚合结果广播回原数据的每一行,所以返回的结果和原DataFrame行数一致(8行),每个分组的众数会重复出现在该分组的每一行,这就是你看到的“扩展后的结果”。

  3. 用applymap():
    applymap()是针对DataFrame的每个元素单独应用函数,和分组聚合逻辑完全无关,它不会进行分组操作,所以根本无法实现你的需求。


额外优化:用Pandas内置众数方法(可选)

其实Pandas已经内置了众数功能,你可以直接用pd.Series.mode,如果有多个众数,取第一个结果就和你的自定义函数效果一致:

result = df.groupby(['id','month'])[['value1','value2']].agg(lambda x: x.mode()[0])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:02:38