Вот один векторизованный способ, использующий strides-tricks
, который просто использует представление в массив с дополнением нулями и является представлением, эффективно использующим память и, следовательно, производительным -
def map2D(a):
n = len(a)
p = np.zeros(n-1,dtype=a.dtype)
a_ext = np.r_[p,a,p]
s0 = a_ext.strides[0]
strided = np.lib.stride_tricks.as_strided
return strided(a_ext[-n:], (len(a_ext)-n+1,n), (-s0,s0), writeable=False)
Пробный прогон -
In [81]: a = np.array([2,5,6,7,9])
In [82]: map2D(a)
Out[82]:
array([[9, 0, 0, 0, 0],
[7, 9, 0, 0, 0],
[6, 7, 9, 0, 0],
[5, 6, 7, 9, 0],
[2, 5, 6, 7, 9],
[0, 2, 5, 6, 7],
[0, 0, 2, 5, 6],
[0, 0, 0, 2, 5],
[0, 0, 0, 0, 2]])
Если вам нужно, чтобы вывод имел собственное пространство памяти, используйте .copy()
Синхронизация массива элементов 5k
-
In [83]: a = np.random.randint(0,9,(5000))
# From this post's soln
In [84]: %timeit map2D(a)
10000 loops, best of 3: 26.3 µs per loop
# If you need output with its own memory space
In [97]: %timeit map2D(a).copy()
10 loops, best of 3: 43.6 ms per loop
# @user3483203's soln
In [87]: %%timeit
...: t = np.pad(a[::-1], (0, len(a)-1), mode='constant')
...: out = np.tril(toeplitz(t, a))
1 loop, best of 3: 264 ms per loop
# @coldspeed's soln
In [89]: %%timeit
...: t = np.pad(a[::-1], (0, len(a)-1), mode='constant')
...: out = np.column_stack([np.roll(t, i) for i in range(len(a))])
1 loop, best of 3: 336 ms per loop