In [40]: a=np.random.randint(1,100, (9,))
In [41]: a
Out[41]: array([ 6, 35, 69, 60, 63, 51, 72, 57, 22])
可广播的索引效果很好:
In [42]: i,j=np.arange(3)[:,None], np.arange(3)
In [43]: i,j
Out[43]:
(array([[0],
[1],
[2]]),
array([0, 1, 2]))
In [44]: i+j
Out[44]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
将其应用于一维数组:
In [45]: a[i+j].reshape(3,3)
Out[45]:
array([[ 6, 35, 69],
[35, 69, 60],
[69, 60, 63]])
它们也可以用于分配
A[i,j] = a[i+j]
In [46]: _[i,j]
Out[46]:
array([[ 6, 35, 69],
[35, 69, 60],
[69, 60, 63]])
as_strided 工作正常,但更难理解,并且容易出错。最近的版本鼓励我们使用sliding_window_view。
In [47]: np.lib.stride_tricks.as_strided(a, shape=(3,3), strides=(8,8))
Out[47]:
array([[ 6, 35, 69],
[35, 69, 60],
[69, 60, 63]])
只要跨步数组只是“读取”,用作视图就更快,但后续操作可能需要复制。
其实对于这个小案例来说,视图生成并没有更快:
In [48]: timeit np.lib.stride_tricks.as_strided(a, shape=(3,3), strides=(8,8))
12.4 µs ± 43.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [49]: %%timeit
...: i,j=np.arange(3)[:,None], np.arange(3)
...: a[i+j].reshape(3,3)
...:
...:
8.9 µs ± 189 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
这些也产生所需的i,j:
np.ix_(range(3),range(3))
np.array(list(itertools.product(range(3), range(3)))).T