
本文介绍如何利用 NumPy 的 sliding_window_view 替代低效的列表推导式或受限的 rolling().apply(),为 DataFrame 快速添加由滑动窗口聚合生成的列表型新列,兼顾性能与可读性。
本文介绍如何利用 numpy 的 `sliding_window_view` 替代低效的列表推导式或受限的 `rolling().apply()`,为 dataframe 快速添加由滑动窗口聚合生成的列表型新列,兼顾性能与可读性。
在 Pandas 中,当需要基于滑动窗口(如每 3 行)将某列的值组合成 Python 列表并存入新列时,常见的误区是试图用 rolling().apply() 直接返回列表——但 rolling().apply() 要求聚合结果为标量(如 float、int),遇到 list 会抛出 TypeError: must be real number, not list 错误。而原始的列表推导式虽逻辑清晰,却因显式循环和频繁调用 .iloc 导致时间复杂度高,数据量大时性能急剧下降。
更优解是借助 NumPy 1.20+ 引入的 sliding_window_view,它以零拷贝方式高效生成滑动窗口视图,再转换为列表即可:
import pandas as pd import numpy as np # 构造示例数据 np.random.seed(150) df = pd.DataFrame(np.random.randint(0, 10, size=(10, 2)), columns=['A', 'B']) # 使用 sliding_window_view 生成长度为 3 的滑动窗口列表 from numpy.lib.stride_tricks import sliding_window_view as swv window_size = 3 windows = swv(df['B'], window_size) # shape: (len(df)-window_size+1, window_size) df['C'] = pd.Series(windows.tolist(), index=df.index[window_size-1:])
执行后,df['C'] 的前 window_size - 1 行自动填充为 NaN(Pandas 默认对齐行为),其余行对应每个窗口的列表,例如第 2 行(索引 2)为 [df.loc[0,'B'], df.loc[1,'B'], df.loc[2,'B']]。
✅ 优势总结:
-
高性能:
sliding_window_view基于内存视图,避免逐行切片,时间复杂度接近 O(n); -
简洁安全:无需手动处理边界条件(如
i >= 2),索引对齐由pd.Series自动完成; -
类型友好:直接支持任意 Python 对象(如
list,dict)作为列值,无rolling().apply()的标量限制。
⚠️ 注意事项:
- 需确保 NumPy ≥ 1.20;旧版本可改用
np.lib.stride_tricks.as_strided(但需谨慎处理内存安全); - 若需自定义窗口函数(如去重、排序后再转列表),可在
swv(...).tolist()后链式处理,例如:[sorted(set(win)) for win in windows]; - 对超大数据集,注意
windows.tolist()会将所有窗口加载至内存,若仅需惰性计算,建议封装为生成器或结合dask处理。
该方法已成为 Pandas 生态中处理“滑动列表列”任务的标准实践,兼顾工程效率与代码可维护性。










