Pandas按三级分组后在滚动窗口中应用自定义函数问题
问题原因与解决方案
你的代码无法运行的核心原因是:rolling().apply()默认会逐列处理数据,传入lambda的x是单个列的Series对象,无法同时访问net和gross两列数据。
要在滚动窗口中同时使用多列执行自定义逻辑,需要让apply把整个窗口的行数据(包含多列)传入函数,以下是可行方案:
方案1:基于numpy数组处理(高效)
调整自定义函数,让它接收二维numpy数组(窗口内的所有行数据),并从中提取需要的列:
修改自定义函数
def fun(arr): # arr是二维数组,行对应窗口内的记录,列对应原DataFrame的列顺序(net、gross) net = arr[:, 0] gross = arr[:, 1] # 这里替换成你实际的复杂计算逻辑 return net.mean() / gross.std()
调用代码
# 先确保DataFrame的列顺序是net、gross(避免索引错误) df = df[['net', 'gross']] # 分组+滚动窗口应用函数 result = df.groupby(['classes', 'names', 'numbers']).rolling(window=500).apply( fun, raw=True # 关键参数:传入窗口的numpy数组而非单列Series )
方案2:转成DataFrame处理(灵活)
如果你的复杂函数依赖Pandas的Series/DataFrame方法,可以在函数内将numpy数组转回DataFrame:
修改自定义函数
def fun(arr): # 将窗口数组转为DataFrame,指定列名对应原数据 window_df = pd.DataFrame(arr, columns=['net', 'gross']) net = window_df['net'] gross = window_df['gross'] # 这里写你的复杂逻辑 return net.mean() / gross.std()
调用代码
和方案1完全一致,同样需要设置raw=True。
注意事项
- 若原DataFrame的列顺序不确定,一定要先显式指定列顺序(如
df = df[['net', 'gross']]),避免数组索引对应错误。 - 对于超大规模数据,方案1的numpy数组处理效率更高;如果逻辑依赖Pandas的高级功能,方案2更灵活。
内容的提问来源于stack exchange,提问作者AlexSB
相关产品推荐
相关产品推荐

