I'm doing some computations on a full matrix that is redundant (i.e. can be a triangle matrix without losing info). I realized I can compute only the lower portion of the triangle for faster results. How can I project the lower triangle into the upper once I'm done?
In other words, how can I reverse the np.tril
method?
print DF_var.as_matrix()
# [[1 1 0 1 1 1 0 1 0 0 0]
# [1 1 1 1 1 0 1 0 1 1 1]
# [0 1 1 0 0 0 0 0 0 0 0]
# [1 1 0 1 0 0 0 0 0 0 0]
# [1 1 0 0 1 0 0 0 0 0 0]
# [1 0 0 0 0 1 1 0 0 0 0]
# [0 1 0 0 0 1 1 0 0 0 0]
# [1 0 0 0 0 0 0 1 1 0 0]
# [0 1 0 0 0 0 0 1 1 0 0]
# [0 1 0 0 0 0 0 0 0 1 0]
# [0 1 0 0 0 0 0 0 0 0 1]]
print np.tril(DF_var.as_matrix())
# [[1 0 0 0 0 0 0 0 0 0 0]
# [1 1 0 0 0 0 0 0 0 0 0]
# [0 1 1 0 0 0 0 0 0 0 0]
# [1 1 0 1 0 0 0 0 0 0 0]
# [1 1 0 0 1 0 0 0 0 0 0]
# [1 0 0 0 0 1 0 0 0 0 0]
# [0 1 0 0 0 1 1 0 0 0 0]
# [1 0 0 0 0 0 0 1 0 0 0]
# [0 1 0 0 0 0 0 1 1 0 0]
# [0 1 0 0 0 0 0 0 0 1 0]
# [0 1 0 0 0 0 0 0 0 0 1]]
How to convert it back to a full matrix?
Since the matrix is symetric, you can do:
Assuming
A
as the input array, few methods are listed below.Approach #1 : Using
np.triu
on a transposed version ofA
-Approach #2 : Avoid
np.triu
with direct summation between A.T and A and then indexing to set diagonal elements -Approach #3 : Same as previous one, but compact using in-builts for indexing -
Approach #4 : Same as previous one, but with boolean indexing to set diagonal elements -
Approach #5 : Using mask based selection for diagonal elements with
np.where
-Approach #6 : Using mask based selection for all elements with
np.where
-Runtime tests
Functions -
Timings -
Looks like the approaches # 2 & #3 are pretty efficient!