Numpy,对每N个连续元素进行分组?

问题描述 投票:0回答:3

我想从数组中提取每 N 个连续元素的组。对于像这样的 numpy 数组:

a = numpy.array([1,2,3,4,5,6,7,8])

我希望有(N=5):

array([[1,2,3,4,5],
       [2,3,4,5,6],
       [3,4,5,6,7],
       [4,5,6,7,8]])

这样我就可以运行进一步的函数,例如平均值和总和。如何生成这样的数组?

python arrays numpy
3个回答
8
投票

一种方法是

broadcasting
-

import numpy as np
out = a[np.arange(a.size - N + 1)[:,None] + np.arange(N)]

样品运行 -

In [31]: a
Out[31]: array([4, 2, 5, 4, 1, 6, 7, 3])

In [32]: N
Out[32]: 5

In [33]: out
Out[33]: 
array([[4, 2, 5, 4, 1],
       [2, 5, 4, 1, 6],
       [5, 4, 1, 6, 7],
       [4, 1, 6, 7, 3]])

6
投票

您可以使用此

博客
中的rolling_window

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

In [37]: a = np.array([1,2,3,4,5,6,7,8])

In [38]: rolling_window(a, 5)
Out[38]:
array([[1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])

我喜欢@Divkar 的解决方案。但是,对于较大的数组和窗口,您可能需要使用

rolling_window

In [55]: a = np.arange(1000)

In [56]: %timeit rolling_window(a, 5)
100000 loops, best of 3: 9.02 µs per loop

In [57]: %timeit broadcast_f(a, 5)
10000 loops, best of 3: 87.7 µs per loop

In [58]: %timeit rolling_window(a, 100)
100000 loops, best of 3: 8.93 µs per loop

In [59]: %timeit broadcast_f(a, 100)
1000 loops, best of 3: 1.04 ms per loop

0
投票

Zero的rolling_window方法很神奇。他引用了一篇文章https://rigtorp.se/2011/01/01/rolling-statistics-numpy.html,该文章在他的回答后进行了更新。

2021 年 4 月 21 日更新:NumPy 现在附带了一个内置函数 slider_window_view ,它正是执行此操作。还有具有滚动平均值、标准差等优化功能的 Bottleneck 库。

按照文档sliding_window_view,你只需编写如下代码即可

import numpy as np
np.lib.stride_tricks.sliding_window_view(a, 5)

然后你得到的结果与上面两个相同。

© www.soinside.com 2019 - 2024. All rights reserved.