Extract upper or lower triangular part of a numpy matrix

I have a matrix A and I want 2 matrices U and L such that U contains the upper triangular elements of A (all elements above and not including diagonal) and similarly for L(all elements below and not including diagonal). Is there a numpy method to do this?

e.g

A = array([[ 4., 9., -3.], [ 2., 4., -2.], [-2., -3., 7.]])
U = array([[ 0., 9., -3.], [ 0., 0., -2.], [ 0., 0., 0.]])
L = array([[ 0., 0., 0.], [ 2., 0., 0.], [-2., -3., 0.]])

3 Answers

Try numpy.triu (triangle-upper) and numpy.tril (triangle-lower).

Code example:

np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
array([[ 1, 2, 3], [ 4, 5, 6], [ 0, 8, 9], [ 0, 0, 12]])
1

To extract the upper triangle values to a flat vector, you can do something like the following:

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a)
#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
a[np.triu_indices(3)]
#or
list(a[np.triu_indices(3)])
#array([1, 2, 3, 5, 6, 9])

Similarly, for the lower triangle, use np.tril.


IMPORTANT

If you want to extract the values that are above the diagonal (or below) then use the k argument. This is usually used when the matrix is symmetric.

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
a[np.triu_indices(3, k = 1)]
# this returns the following
array([2, 3, 6])

EDIT (on 11.11.2019):

To put back the extracted vector into a 2D symmetric array, one can follow my answer here:

1

Use the Array Creation Routines of numpy.triu and numpy.tril to return a copy of a matrix with the elements above or below the k-th diagonal zeroed.

 >>> a = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> a array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> tri_upper_diag = np.triu(a, k=0) >>> tri_upper_diag array([[1, 2, 3], [0, 5, 6], [0, 0, 9]]) >>> tri_upper_no_diag = np.triu(a, k=1) >>> tri_upper_no_diag array([[0, 2, 3], [0, 0, 6], [0, 0, 0]]) >>> tri_lower_diag = np.tril(a, k=0) >>> tri_lower_diag array([[1, 0, 0], [4, 5, 0], [7, 8, 9]]) >>> tri_lower_no_diag = np.tril(a, k=-1) >>> tri_lower_no_diag array([[0, 0, 0], [4, 0, 0], [7, 8, 0]])
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like