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

如何快速在Pandas DataFrame行窗口迭代并处理二维窗口数据?

问题描述

我有一个如下所示的时间序列DataFrame:

datetime                    gesture         left-5-x  ...30 columns omitted
2022-09-27 19:54:54.396680  gesture0255     533 
2022-09-27 19:54:54.403298  gesture0255     534 
2022-09-27 19:54:54.408938  gesture0255     535 
2022-09-27 19:54:54.413995  gesture0255     523 
2022-09-27 19:54:54.418666  gesture0255     522 
... 95 000 rows omitted

我想要创建新列df['cross_correlation'],该列的值由连续多行数据计算得出,即第i行的cross_correlation依赖于i-10到i+10行的数据。

我可以使用df.iterrow()实现,但这不符合Pandas的惯用写法。是否存在类似如下的函数:

df.window(-10, +10).apply(lambda rows: calculate_cross_correlation(rows)

或类似功能的方法?

补充说明

感谢@chris指出可以使用df.rolling(),但我遇到了如下问题:

以下是我要在移动窗口上应用的简化版函数,实际函数要求输入为形状(window_size, num_columns)的完整二维窗口数据,我添加了断言来验证这一点:

def sum_over_2d(x):
    assert len(x.shape) == 2, f'shape of input is {x.shape} and not of length 2'
    return x.sum()

当我使用.rolling结合.apply时:

df.rolling(window=10, center=True).apply(
    sum_over_2d
)

触发了断言错误:

AssertionError: shape of input is (10,) and not of length 2

打印断言前的输入x,得到的是数据集某一列的一维数据:

0    533.0
1    534.0
2    535.0
3    523.0
4    522.0
5    526.0
6    510.0
7    509.0
8    502.0
9    496.0
dtype: float64

我期望输入x是DataFrame或二维numpy数组。

解决方案

Pandas的rolling()默认会按列单独处理数据,所以传给apply()的是一维数组,这就是触发断言错误的原因。要拿到完整的二维窗口数据,试试下面两种方法:

方法1:给apply加raw=False参数

设置raw=False后,apply会把窗口内的所有数据以DataFrame的形式传入函数,正好满足你需要的(window_size, num_columns)形状。另外注意,你要的是i-10到i+10的窗口,窗口大小得设为21(10+1+10),不是之前的10:

def sum_over_2d(x):
    # x现在是窗口内的完整DataFrame
    assert len(x.shape) == 2, f'shape of input is {x.shape} and not of length 2'
    return x.sum().sum()  # 先按列求和,再把列的结果加总

df['cross_correlation'] = df.rolling(window=21, center=True).apply(sum_over_2d, raw=False)

方法2:用numpy滑动窗口工具直接生成二维窗口数据

如果你的计算逻辑比较复杂,用numpy的滑动窗口工具效率更高,适合处理大数量级的数据(比如你的95000行):

import numpy as np

# 先提取所有数值列,排除datetime、gesture这类非数值列
numeric_data = df.select_dtypes(include=[np.number]).values
window_size = 21

# 生成滑动窗口数组,形状是(有效行数, window_size, 列数)
windows = np.lib.stride_tricks.sliding_window_view(numeric_data, window_shape=(window_size, numeric_data.shape[1]))
windows = windows.squeeze(axis=1)  # 去掉多余的维度

# 批量跑你的计算函数
results = np.array([calculate_cross_correlation(window) for window in windows])

# 把结果填回原DataFrame,首尾各10行(window_size//2)没法计算,用NaN填充
df['cross_correlation'] = np.concatenate([
    [np.nan]*10,
    results,
    [np.nan]*10
])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 07:50:30