rolling().apply()中直接传numba函数会报错,因pandas要求函数处理一维ndarray且返回标量,而numba不兼容Series;正确做法是设raw=True、用.values提取纯数组,并确保numba函数仅处理numpy.ndarray、自行处理NaN。

rolling().apply() 里直接传 numba 函数会报错
因为 pandas 的 rolling().apply() 要求传入的函数必须接受一维 ndarray(或 Series),且返回标量或同长度数组;而 numba.jit 编译后的函数默认不支持对 pandas 对象(如 Series)的直接调用,更不兼容其内部索引逻辑。常见错误是:TypingError: Failed in nopython mode... 或 AttributeError: 'numpy.ndarray' object has no attribute 'values'。
关键点:必须确保 numba 函数只处理纯 numpy.ndarray,且输入形状可控(通常是 1D)、无缺失值干扰。
正确做法:先用 numba 编译纯数组函数,再在 apply 中手动提取 .values
绕过 pandas 对象、只喂给 numba 纯 numpy.ndarray 是最稳妥的路径。注意三点:
-
numba.jit函数需加nopython=True和fastmath=True(若计算允许)以获得实际加速 -
rolling().apply()的raw=True参数必须设为True,否则传入的是Series,不是ndarray - 原始数据中若有
NaN,raw=True下仍会传入nan值,numba 函数需自行处理(比如用np.isnan()过滤或提前 dropna)
示例:
import numpy as np import pandas as pd from numba import jit@jit(nopython=True, fastmath=True) def my_rolling_sum(arr):
arr 是 1D numpy.ndarray,可能含 nan
total = 0.0 for x in arr: if not np.isnan(x): total += x return totals = pd.Series([1.0, 2.0, np.nan, 4.0, 5.0]) result = s.rolling(3).apply(my_rolling_sum, raw=True)
替代方案:用 numba 实现完整 rolling 逻辑(跳过 pandas apply)
当窗口计算逻辑复杂、或对性能极致敏感时,
rolling().apply()的 Python 层开销(如每次构造子数组、类型检查)反而成为瓶颈。此时更高效的方式是:
- 用
np.lib.stride_tricks.sliding_window_view(NumPy 1.20+)生成窗口视图 - 把整个窗口数组传给 numba 函数批量处理(避免逐窗口调用)
- 注意边界:sliding_window_view 不自动处理首尾不足窗口长度的情况,需手动 pad 或截断
示例(等效于 rolling(3).sum()):
from numpy.lib.stride_tricks import sliding_window_view@jit(nopython=True) def batch_sum(windows): # windows.shape == (n_windows, window_size) out = np.empty(windows.shape[0], dtype=windows.dtype) for i in range(windows.shape[0]): acc = 0.0 for j in range(windows.shape[1]): if not np.isnan(windows[i, j]): acc += windows[i, j] out[i] = acc return out
arr = s.to_numpy() windows = sliding_window_view(arr, window_shape=3) result_arr = batch_sum(windows) # 返回 (len-2,) 数组
容易被忽略的坑:dtype 不一致和 missing value 处理
numba 对 dtype 敏感,如果输入数组是 float64,但某次 rolling 窗口因全为 NaN 导致 pandas 内部回退为 object 类型,raw=True 仍可能传入非数值数组,触发 numba 编译失败或运行时报错。
务必在调用前统一 dtype 并显式处理缺失值:
- 用
s.astype(np.float64)强制数值类型 - 避免在滚动前混用
None和np.nan(后者才是 numba 可识别的) - 若业务允许,优先用
s.fillna(0)或s.dropna()预处理,比在 numba 函数里反复判断np.isnan更快
真正卡住人的往往不是 numba 怎么写,而是 pandas 滚动窗口怎么把数据“干净地”塞进去 —— 这一步没控好,后面全白搭。










