Pandas expanding自定义聚合函数报错:无数值类型可聚合的原因与修复
问题:expanding聚合lambda报错DataError: No numeric types to aggregate?
问题场景
运行以下代码时抛出DataError: No numeric types to aggregate错误,即使扩展窗口前30行是NaN(理论上支持数值运算),疑惑报错原因及修复方式:
import pandas as pd import numpy as np i = pd.date_range('2000-01-01', '2000-06-01', freq='D') x = pd.DataFrame(data=np.random.randint(0,10, (len(i), 3)), index = i, columns = list('abc')) # 此代码正常运行 # x.expanding(min_periods=30).corr() # 以下代码报错 x.expanding(min_periods=30).aggregate(lambda t: t.corr().stack().loc[[('a', 'b'), ('a', 'c')], :]) # 此代码同样报错 # x.expanding(min_periods=30).aggregate(lambda t: t+1)
错误原因
报错和NaN无关,核心是expanding.aggregate()对自定义函数的返回值有严格要求,而你的lambda返回结构不符合规则:
- 内置的
expanding.corr()是pandas专门实现的扩展窗口方法,它知道如何处理样本数不足min_periods的情况,返回对应结构的NaN,且输出形状符合预期。 expanding.aggregate()要求自定义函数返回标量或与输入DataFrame列数一致的Series,这样每个窗口的结果才能映射为输出的一行:- 第一个lambda返回长度为2的Series,和原DataFrame的3列不匹配,pandas无法识别聚合逻辑。
- 第二个lambda返回和当前窗口同形状的DataFrame(比如前29个窗口是1~29行×3列),完全不符合aggregate的返回值要求,导致pandas无法找到可聚合的数值类型。
修复方案
方案一:先调用内置expanding.corr再筛选(推荐)
利用内置方法处理窗口逻辑,之后按需筛选目标相关对,这也是你自己实现的可行方案:
y = x.expanding(min_periods=30).corr() y.index.names = ['dates', 'letters'] y.columns.name = 'cols' y = y.stack() mi = pd.MultiIndex.from_tuples([('a','b'), ('a','c')], names = ['letters', 'cols']) result = y.to_frame().join(pd.DataFrame(index=mi), on=['letters', 'cols'], how='inner')
方案二:用expanding.apply替代aggregate
如果需要自定义窗口处理逻辑,使用expanding.apply(),它允许返回任意形状的结果:
result = x.expanding(min_periods=30).apply( lambda t: t.corr().stack().loc[[('a', 'b'), ('a', 'c')]], raw=False # 必须设为False,确保t是DataFrame而非numpy数组 )
内容的提问来源于stack exchange,提问作者guyguyguy12345
相关产品推荐
相关产品推荐

