Reputation: 1461
a=np.zeros((3,3,3))
b=np.arange(3)
c=np.arange(9).reshape(3,3)
I wanna put the elements of the array b
or c
along the diagonal (or above/below the diagonal) of the 3d matrix (tensor) a
with respect to a specific axis.
I tired numpy.diagflat
, but it only works for 2d matrix.
For instance, how to make the following matrix?
array([[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 2.]],
[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 2.]],
[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 2.]]])
Upvotes: 1
Views: 2096
Reputation: 53029
For the main diagonals you can use np.einsum
. For example:
>> np.einsum('iii->i', a)[...] = b
>>> a
array([[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 2.]]])
Or:
>>> np.einsum('iji->ji', a)[...] = c
>>> a
array([[[ 0., 0., 0.],
[ 3., 0., 0.],
[ 6., 0., 0.]],
[[ 0., 1., 0.],
[ 0., 4., 0.],
[ 0., 7., 0.]],
[[ 0., 0., 2.],
[ 0., 0., 5.],
[ 0., 0., 8.]]])
Edit: Broadcasting works normally:
>>> np.einsum('ijj->ij', a)[...] = b
>>> a
array([[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 2.]],
[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 2.]],
[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 2.]]])
Subdiagonals also work but are more tricky as some manual slicing is required. For example:
>>> a=np.zeros((3,3,3))
>>> np.einsum('iij->ij', a[:2,1:])[...] = c[1:]
>>> a
array([[[ 0., 0., 0.],
[ 3., 4., 5.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 6., 7., 8.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]])
Upvotes: 6
Reputation: 670
If a sparse matrix will serve your needs, here are some resources:
http://www.janeriksolem.net/sparray-sparse-n-dimensional-arrays-in.html
sparse 3d matrix/array in Python?
Upvotes: -1