You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Pandas字符串Series调用rolling.apply未执行自定义函数?

为什么Object类型Series的rolling.apply没执行你的自定义函数?

这其实是pandas针对不同数据类型的rolling.apply做的特殊优化逻辑导致的,不是说object类型列不能用rolling方法——咱们一步步拆解:

首先看你的测试:数值型Series用rolling.apply(myfunc)会立刻抛出异常,说明函数确实被逐窗口执行了;但换成字符串(object类型)的Series,不管直接传myfunc还是用lambda包装,都没反应,连异常都不抛,这明显是函数根本没被调用。

核心原因:raw参数的默认行为+Object类型的特殊处理

pandas的rolling.apply有个raw参数,默认情况下对于Series是True——意思是把每个窗口的数据以numpy数组的形式传递给自定义函数。

  • 对于数值型Series:numpy数组可以正常处理,pandas会老老实实逐窗口调用你的myfunc,所以异常会触发。
  • 对于Object类型Series:当raw=True时,窗口是一个object类型的numpy数组。pandas内部会判断:这种类型的数组没法执行通用的自定义函数(毕竟object元素可能是任意类型,没有统一运算规则),于是直接跳过了函数执行,直接返回一个全NaN的Series——这就是为什么你看不到异常的原因,函数根本没跑起来。

验证一下?

咱们给myfunc加个打印语句试试:

import pandas as pd
def myfunc(x):
    print("我被调用啦!")
    raise Exception()

# 数值型:会打印+抛异常
pd.Series([1,2,3,4]).rolling(2).apply(myfunc)

# Object型:啥都不打印,直接返回全NaN
pd.Series(["A","A","B","B"]).rolling(2).apply(myfunc)

确实,object类型的情况连打印都没有,说明函数没被执行。

怎么让Object类型的rolling.apply执行自定义函数?

很简单,显式设置raw=False,强制pandas把每个窗口包装成pandas Series对象传递给函数,这时候pandas就会逐窗口执行你的函数了:

pd.Series(["A", "A", "B", "B", "B", "B", "B", "B", "A", "A", "A"]).rolling(3).apply(myfunc, raw=False)

运行这段代码,你会立刻看到抛出的异常,证明myfunc被调用了。

总结一下

  • Object类型列完全可以用rolling方法,只是rolling.apply的默认行为会跳过自定义函数执行;
  • 根源是pandas对object类型的raw模式窗口做了优化,直接返回NaN而不执行函数;
  • 只要设置raw=False,就能让自定义函数在object类型的rolling窗口中正常执行。

内容的提问来源于stack exchange,提问作者r0f1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:41:04