使用numpy实现滚动最大值

r6vfmomb  于 2023-10-19  发布在  其他
关注(0)|答案(4)|浏览(82)

它计算A在长度为K的滑动窗口上的“滚动最大值”(类似于滚动平均值):

import numpy as np
A = np.random.rand(100000)
K = 10
rollingmax = np.array([max(A[j:j+K]) for j in range(len(A)-K)])

但我认为它在性能方面远非最佳。
我知道pandas库有rolling_max,但在我的项目中,我不想使用这种新的依赖关系。

问题:是否有一种简单的方法来计算仅使用numpy的滚动最大值?

kqlmhetl

kqlmhetl1#

我猜这个使用stridesas_strided的小技巧可以完成这项工作:

def max_rolling1(a, window,axis =1):
        shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
        strides = a.strides + (a.strides[-1],)
        rolling = np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
        return np.max(rolling,axis=axis)

为了比较,我根据你的算法定义了另一个函数:

def max_rolling2(A,K):
    rollingmax = np.array([max(A[j:j+K]) for j in range(len(A)-K)])
    return rollingmax

在我的笔记本电脑上,timeit的比较是:
使用:

A = np.random.rand(100000)
K = 10

%timeit X = max_rolling2(A,K)
170 ms ± 19.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit X = max_rolling1(A,K)
> 3.75 ms ± 479 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
woobm2wo

woobm2wo2#

解决方案与Divakar's answer完全相似(完全归功于他),但数组的最终裁剪在此上下文中具有不同的索引:

maximum_filter1d(A, size=K)[K//2:-((K+1)//2)]

范例:

import numpy as np
from scipy.ndimage.filters import maximum_filter1d
A = np.random.randint(0, 10, (50))
K = 5
rollingmax = np.array([max(A[j-K:j]) for j in range(K,len(A))])
rollingmax2 = np.array([max(A[j:j+K]) for j in range(len(A)-K)])
rollingmax3 = maximum_filter1d(A,size=K)[K//2:-((K+1)//2)]
print A, rollingmax, rollingmax2, rollingmax3

[6 7 7 9 4 5 4 7 2 0 3 3 5 9 4 6 6 1 5 2 7 5 7 5 6 0 9 0 5 9 3 7 1 9 5 3 7 5 1 6 9 6 0 5 1 5 5 4 9]
[9 9 9 9 7 7 7 7 5 9 9 9 9 6 7 7 7 7 7 7 9 9 9 9 9 9 9 9 9 9 9 7 9 9 9 9 9 9 9 6 5 5]
[9 9 9 9 7 7 7 7 5 9 9 9 9 6 7 7 7 7 7 7 9 9 9 9 9 9 9 9 9 9 9 7 9 9 9 9 9 9 9 6 5 5]
[9 9 9 9 7 7 7 7 5 9 9 9 9 6 7 7 7 7 7 7 9 9 9 9 9 9 9 9 9 9 9 7 9 9 9 9 9 9 9 6 5 5]

7vux5j2d

7vux5j2d3#

刚刚测试了上面的一些代码,它返回了一些非预期的结果:
input:test_array_input=np.array([1,3,4,5,4,9,7,2,4])
使用rolling max(above)的输出产生:[ 1 3 4 5 4 9 7 2]当检查2个字段的最大值时,即K=1
而期望:[3 4 5 9 9 7 4] -->即,.e第一字段最大值为1和3
我已经实现了:

def udf_rolling_maximum_array(inputarray,numfieldsrolling):
    # example: input ( 1 2 3 4 5 6 2 3 4)  -- 9 fields
    # example: rolling of 2 numfieldsrolling
    # example: output ( 2 3 4 5 6 6 3 4)   -- 8 fields
    # example: rolling of 3 numfieldsrolling
    # example: output (3 4 5 6 6 6 4) -- 7 fields
    import numpy as np
    # setup result array
    k=len(inputarray)-numfieldsrolling+1        
    rollingmax=np.empty(k)
    
    for i in range(k): rollingmax[i] = max(inputarray[i:i+numfieldsrolling])
        
    return rollingmax  #return rolling average array as output of UDF

上面的解决方案rollingmax,rollingmax 1,rollingmax 2在最初的帖子中失败了我的单元测试-比照我的期望。请参阅代码文本中的示例以了解我所期望的行为。我没有优化我的代码的速度-因为我没有庞大的数据集。

9fkzdhlc

9fkzdhlc4#

很高兴找到这些解决方案-直到我尝试用大值的K。有一个~ 6 M浮点数的数组,K = 25000.需要很长时间

相关问题