方法 #1:以下是一种使用模数
和布尔索引
的方法 -
a[np.mod(np.arange(a.size),6)<3]
作为一个函数,它的翻译如下:
def select_in_groups(a, M, N):
return a[np.mod(np.arange(a.size),M+N)<M]
样例逐步运行 -
In [361]: a
Out[361]:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20])
In [362]: np.arange(a.size)
Out[362]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
In [363]: np.mod(np.arange(a.size),6)
Out[363]: array([0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1])
In [364]: np.mod(np.arange(a.size),6) < 3
Out[364]:
array([ True, True, True, False, False, False, True, True, True,
False, False, False, True, True, True, False, False, False,
True, True], dtype=bool)
In [365]: a[np.mod(np.arange(a.size),6)<3]
Out[365]: array([ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20])
方法二:为了提高性能,这里介绍另一种使用NumPy数组步幅
的方法 -
def select_in_groups_strided(a, M, N):
K = M+N
na = a.size
nrows = (1+((na-1)//K))
n = a.strides[0]
out = np.lib.index_tricks.as_strided(a, shape=(nrows,K), strides=(K*n,n))
N = M*(na//K) + (na - (K*(na//K)))
return out[:,:M].ravel()[:N]
样例运行 -
In [545]: a = np.arange(1,21)
In [546]: a
Out[546]:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20])
In [547]: select_in_groups_strided(a,3,3)
Out[547]: array([ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20])
In [548]: a = np.arange(1,25)
In [549]: a
Out[549]:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24])
In [550]: select_in_groups_strided(a,3,3)
Out[550]: array([ 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21])
运行时测试
使用与@Daniel Forsman的时间测试
相同的设置-
In [637]: a = np.arange(1,21)
In [638]: %timeit block_delete(a,3,3)
10000 loops, best of 3: 21 µs per loop
In [639]: %timeit select_in_groups_strided(a,3,3)
100000 loops, best of 3: 6.44 µs per loop
In [640]: a = np.arange(1,2100)
In [641]: %timeit block_delete(a,3,3)
10000 loops, best of 3: 27 µs per loop
In [642]: %timeit select_in_groups_strided(a,3,3)
100000 loops, best of 3: 9.1 µs per loop
In [643]: a = np.arange(999999) + 1
In [644]: %timeit block_delete(a,3,3)
100 loops, best of 3: 2.24 ms per loop
In [645]: %timeit select_in_groups_strided(a,3,3)
1000 loops, best of 3: 1.12 ms per loop
Strided
在不同的尺寸上表现出色,如果你考虑性能方面。
as_strided
的答案,只是无法理解它。 - Daniel F