使用pandas agg添加mode函数触发聚合转换组合错误的解决咨询
Pandas中使用agg同时聚合mode与其他函数的问题解决
问题重现
先构造测试DataFrame:
import pandas as pd import numpy as np df_test = pd.DataFrame(np.array([[1,1,2,2,2],[3,3,4,4,5]]).T,columns=['A','B'])
输出:
A B 0 1 3 1 1 3 2 2 4 3 2 4 4 2 5
使用agg聚合min、max、mean、median时一切正常:
df_test.agg(['min','max','mean','median'])
输出:
A B min 1.0 3.0 max 2.0 5.0 mean 1.6 3.8 median 2.0 4.0
但添加mode到聚合列表后直接报错:
df_test.agg(['min','max','mean','median','mode'])
错误信息:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) /usr/local/lib/python3.7/dist-packages/pandas/core/apply.py in agg_list_like(self) 381 try: --> 382 concatenated = concat(results, keys=keys, axis=1, sort=False) 383 except TypeError as err: 11 frames TypeError: cannot concatenate object of type '<class 'numpy.int64'>'; only Series and DataFrame objs are valid The above exception was the direct cause of the following exception: ValueError Traceback (most recent call last) /usr/local/lib/python3.7/dist-packages/pandas/core/apply.py in agg_list_like(self) 390 raise ValueError( 391 "cannot combine transform and aggregation operations" --> 392 ) from err 393 return result 394 else: ValueError: cannot combine transform and aggregation operations
即使改用每列只有一个众数的DataFrame,错误依然存在:
df_test = pd.DataFrame(np.array([[1,1,2,2,2],[3,3,3,4,4]]).T,columns=['A','B']) df_test.agg(['min','max','mean','median','mode'])
原因分析
mode()方法返回的是Series(单列聚合时)或DataFrame(多列聚合时),而min、max等其他聚合函数返回的是单个标量值。当agg尝试将这些结果拼接成最终输出时,不同类型的返回值(标量 vs Series/DataFrame)会触发拼接错误——pandas无法将标量和Series/DataFrame直接合并。
哪怕单列只有一个众数,mode()返回的也是长度为1的Series,而非标量,因此依然会和其他标量结果冲突。
解决方案
方法1:用Lambda函数提取众数的第一个值
通过lambda函数对每个列的mode结果取第一个元素,确保返回标量:
# 直接聚合,最后一行默认名为<lambda> df_test.agg(['min','max','mean','median', lambda x: x.mode().iloc[0]]) # 重命名行,让结果更清晰 result = df_test.agg(['min','max','mean','median', lambda x: x.mode().iloc[0]]) result.rename(index={result.index[-1]: 'mode'}, inplace=True) print(result)
输出:
A B min 1.0 3.0 max 2.0 4.0 mean 1.6 3.4 median 2.0 3.0 mode 2.0 3.0
方法2:自定义聚合函数
封装一个返回标量的众数函数,代码可读性更好:
def get_mode(x): # 返回众数的第一个值,确保是标量 return x.mode().iloc[0] # 使用自定义函数聚合 result = df_test.agg(['min','max','mean','median', get_mode]) # 重命名行 result.rename(index={result.index[-1]: 'mode'}, inplace=True) print(result)
方法3:用字典形式指定聚合函数
如果需要为不同列配置不同的聚合规则,或者更明确地定义函数,用字典形式:
df_test.agg({ 'A': ['min', 'max', 'mean', 'median', get_mode], 'B': ['min', 'max', 'mean', 'median', get_mode] })
关于mode()[0]尝试失败的说明
之前直接写mode()[0]报错是因为没有正确引用pandas的mode方法——这里的mode必须是针对每个列(Series对象)的方法,而非全局函数。正确的写法是在lambda或自定义函数中对输入的Series调用x.mode().iloc[0],而不是直接调用未定义的mode()。
内容的提问来源于stack exchange,提问作者Musa H. Asyali
相关产品推荐
相关产品推荐

