计算 NumPy 数组中连续的 1
Counting consecutive 1's in NumPy array
[1, 1, 1, 0, 0, 0, 1, 1, 0, 0]
我有一个由 0 和 1 组成的 NumPy 数组,如上所示。我怎样才能像下面这样添加所有连续的 1?任何时候遇到 0,我都会重置。
[1, 2, 3, 0, 0, 0, 1, 2, 0, 0]
我可以使用 for 循环执行此操作,但是是否有使用 NumPy 的矢量化解决方案?
如果列表理解是可以接受的
np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
这是一个向量化的方法 -
def island_cumsum_vectorized(a):
a_ext = np.concatenate(( [0], a, [0] ))
idx = np.flatnonzero(a_ext[1:] != a_ext[:-1])
a_ext[1:][idx[1::2]] = idx[::2] - idx[1::2]
return a_ext.cumsum()[1:-1]
样本运行-
In [91]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [92]: island_cumsum_vectorized(a)
Out[92]: array([1, 2, 3, 0, 0, 0, 1, 2, 0, 0])
In [93]: a = np.array([0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1])
In [94]: island_cumsum_vectorized(a)
Out[94]: array([0, 1, 2, 3, 4, 0, 0, 0, 1, 2, 0, 0, 1])
运行时测试
对于计时,我会使用 OP 的示例输入数组和 repeat/tile 它,希望这应该是 -
小案例:
In [16]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [17]: a = np.tile(a,10) # Repeat OP's data 10 times
# @Paul Panzer's solution
In [18]: %timeit np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
10000 loops, best of 3: 73.4 µs per loop
In [19]: %timeit island_cumsum_vectorized(a)
100000 loops, best of 3: 8.65 µs per loop
更大的案例:
In [20]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [21]: a = np.tile(a,1000) # Repeat OP's data 1000 times
# @Paul Panzer's solution
In [22]: %timeit np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
100 loops, best of 3: 6.52 ms per loop
In [23]: %timeit island_cumsum_vectorized(a)
10000 loops, best of 3: 49.7 µs per loop
不,我想要非常大的箱子:
In [24]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [25]: a = np.tile(a,100000) # Repeat OP's data 100000 times
# @Paul Panzer's solution
In [26]: %timeit np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
1 loops, best of 3: 725 ms per loop
In [27]: %timeit island_cumsum_vectorized(a)
100 loops, best of 3: 7.28 ms per loop
[1, 1, 1, 0, 0, 0, 1, 1, 0, 0]
我有一个由 0 和 1 组成的 NumPy 数组,如上所示。我怎样才能像下面这样添加所有连续的 1?任何时候遇到 0,我都会重置。
[1, 2, 3, 0, 0, 0, 1, 2, 0, 0]
我可以使用 for 循环执行此操作,但是是否有使用 NumPy 的矢量化解决方案?
如果列表理解是可以接受的
np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
这是一个向量化的方法 -
def island_cumsum_vectorized(a):
a_ext = np.concatenate(( [0], a, [0] ))
idx = np.flatnonzero(a_ext[1:] != a_ext[:-1])
a_ext[1:][idx[1::2]] = idx[::2] - idx[1::2]
return a_ext.cumsum()[1:-1]
样本运行-
In [91]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [92]: island_cumsum_vectorized(a)
Out[92]: array([1, 2, 3, 0, 0, 0, 1, 2, 0, 0])
In [93]: a = np.array([0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1])
In [94]: island_cumsum_vectorized(a)
Out[94]: array([0, 1, 2, 3, 4, 0, 0, 0, 1, 2, 0, 0, 1])
运行时测试
对于计时,我会使用 OP 的示例输入数组和 repeat/tile 它,希望这应该是
小案例:
In [16]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [17]: a = np.tile(a,10) # Repeat OP's data 10 times
# @Paul Panzer's solution
In [18]: %timeit np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
10000 loops, best of 3: 73.4 µs per loop
In [19]: %timeit island_cumsum_vectorized(a)
100000 loops, best of 3: 8.65 µs per loop
更大的案例:
In [20]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [21]: a = np.tile(a,1000) # Repeat OP's data 1000 times
# @Paul Panzer's solution
In [22]: %timeit np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
100 loops, best of 3: 6.52 ms per loop
In [23]: %timeit island_cumsum_vectorized(a)
10000 loops, best of 3: 49.7 µs per loop
不,我想要非常大的箱子:
In [24]: a = np.array([1, 1, 1, 0, 0, 0, 1, 1, 0, 0])
In [25]: a = np.tile(a,100000) # Repeat OP's data 100000 times
# @Paul Panzer's solution
In [26]: %timeit np.concatenate([np.cumsum(c) if c[0] == 1 else c for c in np.split(a, 1 + np.where(np.diff(a))[0])])
1 loops, best of 3: 725 ms per loop
In [27]: %timeit island_cumsum_vectorized(a)
100 loops, best of 3: 7.28 ms per loop