Pandas groupby的agg函数无法处理Categorical分类列问题
Pandas groupby.agg 对Categorical类型列的支持说明
结论先行:Pandas的groupby.agg本身原生支持处理Categorical分类类型列,你遇到的分类列被自动丢弃的问题,是自定义聚合函数的返回值类型校验不通过导致的,并非方法本身不支持该类型。
问题根因
- 触发告警丢列的核心逻辑是:当聚合操作作用于Categorical列时,Pandas会默认校验聚合返回值是否符合该列的类型约束。你在lambda中通过
x.value_counts().index[0]拿到的是Categorical类型的标量对象,在Pandas 1.x~2.0的部分版本中,这个返回值会被误判定为不匹配原列的Categorical dtype,最终被判定为聚合失败、自动丢弃列,抛出你看到的告警。 - 你写的类型判断逻辑存在小缺陷:
np.dtype(x)=='float16'的写法在入参x是Categorical类型时,拿到的是CategoricalDtype实例,直接和字符串'float16'比较虽然能走到else分支,但不会改变返回值校验失败的结果。
修复方案
方案1:修正类型判断+转换返回值类型(最小改动)
只需要把dtype判断改成取dtype的name属性做比较,同时把Categorical列的聚合返回值转成原生Python标量,绕过类型校验即可:
import pandas as pd import numpy as np i = pd.DataFrame({"A":["a","a","a","b","c","c"],"B":[1,2,3,4,5,6],"C":[ "NaN" ,"b","NaN","b","c","c"]}) i['A'] = i['A'].astype('category') i['B'] = i['B'].astype('float16') i['C'] = i['C'].astype('category') res = i.groupby("A", as_index=False)[["B","C"]].agg( lambda x: x.mean() if x.dtype.name == 'float16' else x.value_counts().index[0].item() ) print(res)
运行后得到预期输出:
A B C 0 a 2.0 NaN 1 b 4.0 b 2 c 5.5 c
方案2:按列类型显式指定聚合规则(更稳定,推荐生产环境用)
不要用单个lambda做全列分支判断,提前按列的dtype拆分,给不同类型的列单独指定聚合逻辑,从根源上避免隐式类型校验冲突:
# 拆分不同类型的待聚合列 float_cols = i.select_dtypes(include=['float16']).columns.tolist() cat_cols = i.select_dtypes(include=['category']).columns.difference(['A']).tolist() # 构造聚合规则字典 agg_config = {} agg_config.update({col: 'mean' for col in float_cols}) agg_config.update({col: lambda x: x.value_counts().index[0] for col in cat_cols}) res = i.groupby("A", as_index=False).agg(agg_config)
补充说明
Pandas 2.1及以上版本已经优化了Categorical列聚合时的类型校验逻辑,多数场景下即使不做返回值类型转换,也不会出现丢列告警。但显式指定列聚合规则的写法兼容性更好,能避免跨版本运行时出现隐式异常。
内容的提问来源于stack exchange,提问作者Jas
相关产品推荐
相关产品推荐

