【问题标题】:Creating a tumbling windows in python在python中创建一个翻滚窗口
【发布时间】:2020-03-30 10:27:29
【问题描述】:

只是想知道是否有一种方法可以在 python 中构建一个翻滚窗口。例如,如果我有 list/ndarray ,listA = [3,2,5,9,4,6,3,8,7,9]。那我怎么能找到前3个项目(3,2,5)-> 5中的最大值,然后是接下来的3个项目(9,4,6)-> 9等等......有点像打破它最多部分并找到最大值。所以最终结果将是列表[5,9,8,9]

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 是的,它确实有效。

标签: python numpy


【解决方案1】:

方法 #1: 使用 np.maximum.reduceat 的窗口最大值的单线 -

In [118]: np.maximum.reduceat(listA,np.arange(0,len(listA),3))
Out[118]: array([5, 9, 8, 9])

使用np.r_ 变得更加紧凑-

np.maximum.reduceat(listA,np.r_[:len(listA):3])

方法 #2: 通用 ufunc 方式

这是一个通用 ufunc 的函数和作为参数的窗口长度 -

def windowed_ufunc(a, ufunc, W):
    a = np.asarray(a)
    n = len(a)
    L = W*(n//W)
    out = ufunc(a[:L].reshape(-1,W),axis=1)
    if n>L:
        out = np.hstack((out, ufunc(a[L:])))
    return out

示例运行 -

In [81]: a = [3,2,5,9,4,6,3,8,7,9]

In [82]: windowed_ufunc(a, ufunc=np.max, W=3)
Out[82]: array([5, 9, 8, 9])

在其他 ufunc 上 -

In [83]: windowed_ufunc(a, ufunc=np.min, W=3)
Out[83]: array([2, 4, 3, 9])

In [84]: windowed_ufunc(a, ufunc=np.sum, W=3)
Out[84]: array([10, 19, 18,  9])

In [85]: windowed_ufunc(a, ufunc=np.mean, W=3)
Out[85]: array([3.33333333, 6.33333333, 6.        , 9.        ])

基准测试

数组数据上 NumPy 解决方案的时间安排,样本数据按10000x 放大 -

In [159]: a = [3,2,5,9,4,6,3,8,7,9]

In [160]: a = np.tile(a, 10000)

# @yatu's soln
In [162]: %timeit moving_maxima(a, w=3)
435 µs ± 8.54 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# From this post - app#1
In [167]: %timeit np.maximum.reduceat(a,np.arange(0,len(a),3))
353 µs ± 2.55 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# From this post - app#2
In [165]: %timeit windowed_ufunc(a, ufunc=np.max, W=3)
379 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

  • 有没有办法将最大值放置在与原始数组大小相同的数组中?例如:array;(2,5,6,7,4,2)... 从每 3 个中提取最大值将创建一个数组 (6,7)。但是我们如何创建一个看起来像 (0,0,6,7,0,0) 的数组呢?
【解决方案2】:

如果你想要一个单行,你可以使用列表推导:

listA = [3,2,5,9,4,6,3,8,7,9]
listB=[max(listA[i:i+3]) for i in range(0,len(listA),3)]
print (listB)

它返回:

[5, 9, 8, 9]

当然,代码可以更动态地编写:如果您想要不同的窗口大小,只需将3 更改为任意整数即可。

【讨论】:

    【解决方案3】:

    使用 numpy,您可以用零扩展列表,使其长度可被窗口大小整除,并沿第二个轴重塑和计算 max

    def moving_maxima(a, w):
        mod = len(a)%w
        d = w if mod else mod
        x = np.r_[a, [0]*(d-mod)]
        return x.reshape(-1,w).max(1)
    

    一些例子:

    moving_maxima(listA,2)
    # array([3., 9., 6., 8., 9.])
    
    moving_maxima(listA,3)
    #array([5, 9, 8, 9])
    
    moving_maxima(listA,4)
    #array([9, 8, 9])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 2011-04-08
      • 2011-07-29
      • 2018-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多