Вы можете создать массив нулей с желаемой формой, а затем использовать простое индексирование, чтобы заполнить ожидаемые индексы столбцами вашего массива:
x, y = a.shape
arr = np.zeros((x, y, y))
ind = np.arange(y)
arr[ind,:,ind] = a.T
Демонстрация:
In [40]: a = np.array([
...: [ 5 ,10 ,15, 20],
...: [ 6, 12, 18, 24],
...: [ 7, 14, 21, 28],
...: [ 8, 16, 24, 32]
...: ])
In [43]: arr[np.arange(4),:,np.arange(4)] = a.T
In [44]: arr
Out[44]:
array([[[ 5., 0., 0., 0.],
[ 6., 0., 0., 0.],
[ 7., 0., 0., 0.],
[ 8., 0., 0., 0.]],
[[ 0., 10., 0., 0.],
[ 0., 12., 0., 0.],
[ 0., 14., 0., 0.],
[ 0., 16., 0., 0.]],
[[ 0., 0., 15., 0.],
[ 0., 0., 18., 0.],
[ 0., 0., 21., 0.],
[ 0., 0., 24., 0.]],
[[ 0., 0., 0., 20.],
[ 0., 0., 0., 24.],
[ 0., 0., 0., 28.],
[ 0., 0., 0., 32.]]])
Тест с другим ответом, использующим np.eye()
, умножение и трансляцию, показывает, что этот ответ в два раза быстрее.
In [46]: def use_zeros(arr):
...: x, y = arr.shape
...: z = np.zeros((x, y, y))
...: ind = np.arange(y)
...: z[ind,:,ind] = a.T
...: return z
...:
...:
In [47]: def use_eye(arr):
...: return arr*np.eye(arr.shape[1])[:,np.newaxis]
...:
...:
In [48]: a = np.arange(10000).reshape(100,100)
In [49]: %timeit use_zeros(a)
1.23 ms ± 14.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [50]: %timeit use_eye(a)
2.47 ms ± 23.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)