Home > Enterprise >  How to diagonally populate a matrix using numpy diagonal
How to diagonally populate a matrix using numpy diagonal

Time:11-11

Suppose I have:

arr1 = np.array([[1,2,3,4,5], [6,7,8,9,10], [11,12,13,14,15], [16,17,18,19,20], [21,22,23,24,25]])

And the empty matrix:

matrix = np.zeros((10, 10))
matrix[:] = np.NaN

I want to populate matrix with each element within arr1, but diagonally. This is the expected output:

array([[ nan, nan, nan,  nan,  nan, nan, nan, nan, nan, nan],
       [ 1,   nan, nan,  nan,  nan, nan, nan, nan, nan, nan],
       [ 6,   2,   nan,  nan,  nan, nan, nan, nan, nan, nan],
       [ 11,  7,   3,    nan,  nan, nan, nan, nan, nan, nan],
       [ 16,  12,  8,    4,    nan, nan, nan, nan, nan, nan],
       [ 21,  17,  13,   9,    5,   nan, nan, nan, nan, nan],
       [ nan, 22,  18,   14,   10,  nan, nan, nan, nan, nan],
       [ nan, nan, 23,   19,   15,  nan, nan, nan, nan, nan],
       [ nan, nan, nan,  24,   20,  nan, nan, nan, nan, nan],
       [ nan, nan,  nan, nan,  25,  nan, nan, nan, nan, nan]])

This is what I have tried so far without succeeding:

arr1 = np.array([[1,2,3,4,5], [6,7,8,9,10], [11,12,13,14,15], [16,17,18,19,20], [21,22,23,24,25]])
matrix = np.zeros((10, 10))
matrix[:] = np.NaN

for i, array in enumerate(arr1):                                 
    for row_matrix in matrix:
        row_matrix = np.diag(array, -i-1)
        break

This is the output I have from the above code:

array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 21, 0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0, 22,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 23,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0, 24,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0, 25,  0,  0,  0,  0,  0]])

CodePudding user response:

Try:

for i, col in enumerate(arr1.T, 1):
    matrix[i : i   len(col), i - 1] = col

print(matrix)

Prints:

[[nan nan nan nan nan nan nan nan nan nan]
 [ 1. nan nan nan nan nan nan nan nan nan]
 [ 6.  2. nan nan nan nan nan nan nan nan]
 [11.  7.  3. nan nan nan nan nan nan nan]
 [16. 12.  8.  4. nan nan nan nan nan nan]
 [21. 17. 13.  9.  5. nan nan nan nan nan]
 [nan 22. 18. 14. 10. nan nan nan nan nan]
 [nan nan 23. 19. 15. nan nan nan nan nan]
 [nan nan nan 24. 20. nan nan nan nan nan]
 [nan nan nan nan 25. nan nan nan nan nan]]

CodePudding user response:

Without any iteration

n=len(arr1)
arr2=np.full((2*n, 2*n 1), np.nan)
arr2[:n,1:n 1]=arr1.T
arr2.resize((2*n,2*n))
matrix=arr2.T

Just taking advantage of the fact that there a n values, and n 1 nan in between, when you read "left to right, row by row" the transposed wanted result. So, well, we do that simply in a 10x11 matrix, in which, when copied, values of arr1 have the exact same property (5 values, then 6 nan, per rows). So, after resize to 10x10, those 5 values then 6 nans imply a shift).

So, everything is about copying the data in a 1 column too big matrix, then resize it. Plus some transpose play.

Timings

For your 5x5 example

Method Timing
Yours 35.3 μs
Andrej's 15.7 μs
This one 9.1 μs

On 5000x5000 example

Method Timing
Yours 70.24 sec
Andrej's 0.54 sec
This one 0.31 sec
  • Related