Given 3D arr
, I would like to fill all dioganal element equal to 1
.
np.random.seed(0)
arr=np.random.rand(3,4,4)
expected outpud
1,0.71519,0.60276,0.54488
0.42365,1,0.43759,0.89177
0.96366,0.38344,1,0.52889
0.56804,0.92560,0.07104,1
1,0.83262,0.77816,0.87001
0.97862,1,0.46148,0.78053
0.11827,0.63992,1,0.94467
0.52185,0.41466,0.26456,1
1,0.56843,0.01879,0.61764
0.61210,1,0.94375,0.68182
0.35951,0.43703,1,0.06023
0.66677,0.67064,0.21038,1
Assign the fill_diagonal
as below
arr=np.fill_diagonal(arr, 1)
return an error
ValueError: All dimensions of input must be of equal length
May I know how to properly fill diagonal equal to 1 for a 3d array
What being tried so far
arr[:,:,0] = np.diag((1,1))
ValueError: could not broadcast input array from shape (2,2) into shape (3,4)
What to avoid
Using for-loop
with the fill_diagonal
CodePudding user response:
try this:
r = np.arange(4)
arr[:, r, r] = 1
Example:
arr = np.arange(3*4*4).reshape(3,4,4)
r = np.arange(4)
arr[:, r, r] = 1
output:
array([[[ 1, 1, 2, 3],
[ 4, 1, 6, 7],
[ 8, 9, 1, 11],
[12, 13, 14, 1]],
[[ 1, 17, 18, 19],
[20, 1, 22, 23],
[24, 25, 1, 27],
[28, 29, 30, 1]],
[[ 1, 33, 34, 35],
[36, 1, 38, 39],
[40, 41, 1, 43],
[44, 45, 46, 1]]])
CodePudding user response:
This is the best way
import numpy as np
np.random.seed(0)
arr=np.random.rand(3,4,4)
d1, d2, d3 = arr.shape
for i in range(d1):
np.fill_diagonal(arr[i,:,:], 1)
CodePudding user response:
You can use np.diag_indices
to generate indices for a diagonal of a 2D subarray and then use indexing and a view in which you assign values:
import numpy
rng = np.random.default_rng(0)
arr = rng.random((3,4,4))
diag = np.diag_indices(4, ndim=2)
for d1 in range(arr.shape[0]):
arr_view = arr[d1, :]
arr_view[diag] = 1
If all your dimensions are equally-sized (shape as (n, n, n)
), you can directly use the np.fill_diagonal
function that you tried before.
EDIT:
Without using a for-loop, you can use
rng = np.random.default_rng(0)
arr = rng.random((3,4,4))
# Build a custom indexing with proper broadcasting
diag = np.arange(arr.shape[0])[:, None], *np.diag_indices(arr.shape[1], ndim=2)
arr[diag] = 1
This works because the np.diag_indices(n, ndim=m)
function only gives you a m
-tuple of (n)
-shaped ndarrays.
Consequently, you can just augment the return value with a (k)
-shaped ndarray if you have a (k, n, n)
array. For Numpy to be able to broadcast the three arrays to the correct shape, you then only need to add a new axis (via the None
) to the first ndarray.