Search code examples
pythonarrayslistmatrixdiagonal

Replace all the subdiagonals of a matrix for a given k in Python


I would like to replace all values of the subdiagonals under the k-diagonal.

For example :

We first import the numpy library :

import numpy as np

Then we create the matrix :

In [14]: matrix = np.matrix('1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1')

We are then getting :

In [15]: print(matrix)

Out[16]: 
    [[1 1 1 1 1 1]
     [1 1 1 1 1 1]
     [1 1 1 1 1 1]
     [1 1 1 1 1 1]
     [1 1 1 1 1 1]]

We then get the diagonals under the k-diagonal for k = 1 for example :

In [17]: lowerdiags = [np.diag(matrix, k=e+1).tolist() for e in range(-len(matrix), k)]

In [18]: print(lowerdiags)

Out[19]: [[1], [1, 1], [1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]

And, I'm stuck there, what should I add for it to be for k = 1 and replace all values per 0, like that: (Knowing that we just found the subdiagonals)

[[0 1 1 1 1 1]
 [0 0 1 1 1 1]
 [0 0 0 1 1 1]
 [0 0 0 0 1 1]
 [0 0 0 0 0 1]]

or even for k = 0 :

[[1 1 1 1 1 1]
 [0 1 1 1 1 1]
 [0 0 1 1 1 1]
 [0 0 0 1 1 1]
 [0 0 0 0 1 1]]

Thank you for your help and your patience.


Solution

  • I found a way by using the numpy method : fill_diagonal and by moving around the different k :

    # Import numpy library
    import numpy as np
    
    def Exercise_3(matrix, k):
        # print initial matrix
        print(matrix)
        
        for k in range(-len(matrix)+1, k):
            if k < 0:
                # Smart slicing when filling diagonals with "np.fill_diagonal" on our matrix for lower diagonals
                np.fill_diagonal(matrix[-k:, :k], 0)
            if k > 0:
                # Smart slicing when filling diagonals with "np.fill_diagonal" on our matrix for upper diagonals
                np.fill_diagonal(matrix[:-k, k:], 0)
            if k == 0:
                # Just replace the main diagonal by 0
                np.fill_diagonal(matrix, 0)
            # print to see each change on the matrix    
            #print(matrix)
            
            #print(k)
    
        return matrix
    
    def main():
        k = 0
        # an another way of creating a matrix
        #matrix = np.matrix('1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1; 1 1 1 1 1 1')
        # matrix of 5 rows and 5 columns filled by 1
        matrix = np.array(([1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]))
        
        NewMatrix = Exercise_3(matrix, k)
        print(NewMatrix)
    
    main()