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

Python Pandas滚动窗口最大值索引高效计算方法咨询

高效实现滚动窗口内最大值的位置计算

你的核心问题是现有基于rolling+lambda的实现效率过低,这是因为每个窗口都要执行Python层面的循环和对象操作,对于238万行的数据来说开销极大。以下是两种远快于原方案的实现方式:

方案一:Numba 加速数组运算

利用Numba将Python函数编译为机器码,直接操作numpy数组,避免pandas滚动窗口的Python层开销:

import numba
import numpy as np
import pandas as pd

@numba.jit(nopython=True)
def rolling_max_idx(arr, window_size):
    n = len(arr)
    result = np.full(n, np.nan)
    # 遍历每个窗口的结束位置(窗口大小达标后开始计算)
    for i in range(window_size - 1, n):
        start = i - window_size + 1
        # 截取当前窗口的数组片段
        window = arr[start:i+1]
        # 找到最大值在窗口内的位置(从1开始计数)
        max_pos = np.argmax(window) + 1
        result[i] = max_pos
    return result

# 应用到你的DataFrame,窗口大小设为1000
window_size = 1000
df['High time'] = rolling_max_idx(df['Bid'].values, window_size)

方案二:单调队列优化(O(n) 时间复杂度)

对于超大窗口或超大数据量,单调队列可以实现线性时间复杂度的计算,每个元素仅进出队列一次,效率最高:

from collections import deque
import numpy as np

def rolling_max_idx_deque(arr, window_size):
    n = len(arr)
    result = np.full(n, np.nan)
    # 双端队列存储索引,对应arr值保持单调递减
    dq = deque()
    
    for i in range(n):
        # 移除队列中比当前元素小的索引(不可能成为后续窗口的最大值)
        while dq and arr[i] >= arr[dq[-1]]:
            dq.pop()
        # 添加当前索引到队列
        dq.append(i)
        # 移除窗口范围外的索引
        while dq[0] <= i - window_size:
            dq.popleft()
        # 窗口大小达标后,计算最大值在窗口内的位置
        if i >= window_size - 1:
            max_idx = dq[0]
            # 转换为1-1000的窗口内位置
            result[i] = i - max_idx + 1
    return result

# 应用到你的DataFrame
df['High time'] = rolling_max_idx_deque(df['Bid'].values, 1000)

原方案低效原因

原代码中rolling+lambda的实现,每个窗口都要创建子Series、获取索引、执行np.argmax,涉及大量Python对象的创建和销毁,属于O(n*window)的时间复杂度,在数据量较大时会产生严重的性能瓶颈。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:23:27