
本文介绍使用 numpy.sliding_window_view 替代低效列表推导式或受限的 rolling().apply(),实现将 DataFrame 某列的滑动窗口数据(如每 3 行)转为列表并存入新列,兼顾性能与可读性。
本文介绍使用 `numpy.sliding_window_view` 替代低效列表推导式或受限的 `rolling().apply()`,实现将 dataframe 某列的滑动窗口数据(如每 3 行)转为列表并存入新列,兼顾性能与可读性。
在 Pandas 中,当需要基于滑动窗口(如每 3 行)将某列的值聚合为 Python 列表并写入新列时,常见的误区是尝试用 rolling(window=3).apply(lambda x: list(x)) —— 这会报错 TypeError: must be real number, not list。原因在于 rolling().apply() 默认要求返回标量数值(用于统计计算),不支持直接返回非标量对象(如 list),即使设置 raw=False 也无法绕过该限制。
更高效、更规范的解决方案是借助 NumPy 1.20+ 引入的 sliding_window_view,它专为生成滑动窗口视图而设计,返回一个形状为 (n - window + 1, window) 的二维数组,再通过 .tolist() 可直接转为嵌套列表,最后封装为 pd.Series 并对齐索引即可。
以下为完整实现示例:
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 的滑动列表列 'C' from numpy.lib.stride_tricks import sliding_window_view as swv N = 3 windowed_lists = swv(df['B'], N).tolist() # → [[9,2,5], [2,5,9], ..., [1,9,7]] df['C'] = pd.Series(windowed_lists, index=df.index[N-1:]) # 自动对齐:前 N-1 行为 NaN print(df)
输出结果中,前两行(索引 0 和 1)的 'C' 值为 NaN(因窗口不足),从索引 2 开始填充对应三元列表,与预期完全一致。
⚠️ 注意事项:
-
sliding_window_view要求 NumPy ≥ 1.20;旧版本可升级pip install --upgrade numpy; - 返回的
Series默认以df.index[N-1:]为索引,未覆盖部分自动补NaN,无需手动填充; - 若需保留
None(而非NaN),可在赋值后执行:df['C'] = df['C'].where(df['C'].notna(), None); - 相比原始列表推导式(O(n²) 时间复杂度),此方法为 O(n),在百万级数据上性能提升显著。
总结:当 apply 遇到非标量返回限制时,应跳出 Pandas 单一 API 思维,善用 NumPy 底层向量化工具。sliding_window_view 不仅语义清晰、代码简洁,更是处理滑动列表类任务的推荐实践。










