How to convert a triangle matrix into a square in NumPy?

I do some calculations on a complete matrix that is redundant (i.e. it can be a triangle matrix without loss of information). I realized that I can only calculate the bottom of the triangle faster. How can I project the bottom triangle into the top as soon as I finish?

In other words, how can I change 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 to a full matrix?

+6
source share
2 answers

Assuming A as an input array, several methods are listed below.

Approach # 1: Using np.triu for transposed version A -

 np.triu(AT,1) + A 

Approach # 2: Avoid np.triu with direct summation between AT and A and then indexing to set diagonal elements -

 out = AT + A idx = np.arange(A.shape[0]) out[idx,idx] = A[idx,idx] 

Approach No. 3: The same as the previous one, but compact using the built-in constructions for indexing -

 out = AT + A np.fill_diagonal(out,np.diag(A)) 

Approach # 4: Same as previous, but with boolean indexing to set diagonal elements -

 out = AT + A mask = np.eye(out.shape[0],dtype=bool) out[mask] = A[mask] 

Approach # 5: Using mask-based selections for diagonal elements with np.where -

 np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A) 

Approach # 6: Using mask selection for all elements with np.where -

 np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),AT,A) 

Runtime tests

Functions -

 def func1(A): return np.triu(AT,1) + A def func2(A): out = AT + A idx = np.arange(A.shape[0]) out[idx,idx] = A[idx,idx] return out def func3(A): out = AT + A np.fill_diagonal(out,np.diag(A)) return out def func4(A): out = AT + A mask = np.eye(out.shape[0],dtype=bool) out[mask] = A[mask] return out def func5(A): return np.where(np.eye(A.shape[0],dtype=bool),A,A.T+A) def func6(A): return np.where(np.triu(np.ones(A.shape[0],dtype=bool),1),AT,A) 

Dates -

 In [140]: # Input array ...: N = 5000 ...: A = np.tril(np.random.randint(0,9,(N,N))) ...: In [141]: %timeit func1(A) ...: %timeit func2(A) ...: %timeit func3(A) ...: %timeit func4(A) ...: %timeit func5(A) ...: %timeit func6(A) ...: 1 loops, best of 3: 617 ms per loop 1 loops, best of 3: 354 ms per loop 1 loops, best of 3: 354 ms per loop 1 loops, best of 3: 395 ms per loop 1 loops, best of 3: 597 ms per loop 1 loops, best of 3: 440 ms per loop 

Looks like approaches # 2 and # 3 are pretty effective!

+5
source

Since the matrix is ​​symmetric, you can do:

 m = np.array([1,1,0,1,1,1,0,1,1]).reshape((3,3)) # after some computation you get x x = np.tril(m) m_recomposed = x + x.transpose() - np.diag(np.diag(x)) #array([[1, 1, 0], # [1, 1, 1], # [0, 1, 1]]) #In [152]: np.array_equal(m, m_recomposed) #Out[152]: True 
+1
source

All Articles