Pandas自定义函数在groupby apply/agg中报错:numpy.float64不可调用
解决按分组计算加权平均值的apply/agg报错问题
错误原因分析
第一个错误:'numpy.float64' object is not callable
你调用apply(avg_w(df))时,直接执行了avg_w(df)并将结果(一个numpy.float64数值)传给了apply,但apply需要接收的是函数对象(即函数名本身,不要加括号调用),而非已经计算出的数值。这就导致Python试图把一个数值当作函数来执行,因此抛出“不可调用”的错误。
第二个错误:TypeError: unhashable type: 'dict'
你修改后的apply({'avgw': [avg_w2(dt)]})存在两个问题:
apply不支持这种字典格式的参数(这类格式是agg方法的用法);- 同样犯了直接调用函数的错误:
avg_w2(dt)会立即执行并返回结果,而非传递函数对象。
正确解决方案
方案1:使用apply传递函数对象(最简方式)
你的第一个函数avg_w逻辑是正确的,只需修正apply的调用方式,直接传递函数名即可:
import pandas as pd import numpy as np df = pd.DataFrame([['RETIRO', 65, 1, 10.7], ['SAN NICOLAS',116, 1, 23.2], ['RETIRO', 101, 2, 28.7], ['FLORES', 136 , 2, 23.5]], columns=['BARRIO', 'HOGARES', 'COMUNA', 'NSE']) def avg_w(dt): return np.average(a = dt.NSE, weights = dt.HOGARES) # 正确调用:传递函数对象,而非执行结果 result = df.loc[:,['COMUNA','NSE','HOGARES']].groupby(['COMUNA']).apply(avg_w) print(result)
输出结果:
COMUNA 1 18.710994 2 25.716034 dtype: float64
方案2:返回Series以得到DataFrame格式结果
如果希望返回结构更清晰的DataFrame,可以修改函数返回pd.Series,再配合apply:
def avg_w2(dt): return pd.Series({'weighted_avg_NSE': np.average(dt.NSE, weights=dt.HOGARES)}) result = df.groupby(['COMUNA']).apply(avg_w2) print(result)
输出结果:
weighted_avg_NSE COMUNA 1 18.710994 2 25.716034
方案3:使用agg结合lambda函数(无需自定义函数)
可以直接用agg方法配合lambda表达式,更简洁地实现需求:
result = df.groupby(['COMUNA']).agg( weighted_avg_NSE=lambda x: np.average(x['NSE'], weights=x['HOGARES']) ) print(result)
输出结果与方案2一致。
内容的提问来源于stack exchange,提问作者flora93
相关产品推荐
相关产品推荐

