Making a numpy ndarray matrix symmetric Making a numpy ndarray matrix symmetric numpy numpy

Making a numpy ndarray matrix symmetric


Found a following solution which works for me:

import numpy as npW = np.maximum( A, A.transpose() )


Use the NumPy tril and triu functions as follows. It essentially "mirrors" elements in the lower triangle into the upper triangle.

import numpy as npA = np.array([[1, 0, 0, 0], [0, 2, 0, 0], [1, 0, 2, 0], [0, 1, 0, 3]])W = np.tril(A) + np.triu(A.T, 1)

tril(m, k=0) gets the lower triangle of a matrix m (returns a copy of the matrix m with all elements above the kth diagonal zeroed). Similarly, triu(m, k=0) gets the upper triangle of a matrix m (all elements below the kth diagonal zeroed).

To prevent the diagonal being added twice, one must exclude the diagonal from one of the triangles, using either np.tril(A) + np.triu(A.T, 1) or np.tril(A, -1) + np.triu(A.T).

Also note that this behaves slightly differently to using maximum. All elements in the upper triangle are overwritten, regardless of whether they are the maximum or not. This means they can be any value (e.g. nan or inf).


For what it is worth, using the MATLAB's numpy equivalent you mentioned is more efficient than the link @plonser added.

In [1]: import numpy as npIn [2]: A = np.zeros((4, 4))In [3]: np.fill_diagonal(A, np.arange(4)+1)In [4]: A[2:,:2] = np.eye(2)# numpy equivalent to MATLAB:In [5]: %timeit W = np.maximum( A, A.T)100000 loops, best of 3: 2.95 µs per loop# method from linkIn [6]: %timeit W = A + A.T - np.diag(A.diagonal())100000 loops, best of 3: 9.88 µs per loop

Timing for larger matrices can be done similarly:

In [1]: import numpy as npIn [2]: N = 100In [3]: A = np.zeros((N, N))In [4]: A[2:,:N-2] = np.eye(N-2)In [5]: np.fill_diagonal(A, np.arange(N)+1)In [6]: print AOut[6]: array([[   1.,    0.,    0., ...,    0.,    0.,    0.],       [   0.,    2.,    0., ...,    0.,    0.,    0.],       [   1.,    0.,    3., ...,    0.,    0.,    0.],       ...,        [   0.,    0.,    0., ...,   98.,    0.,    0.],       [   0.,    0.,    0., ...,    0.,   99.,    0.],       [   0.,    0.,    0., ...,    1.,    0.,  100.]])# numpy equivalent to MATLAB:In [6]: %timeit W = np.maximum( A, A.T)10000 loops, best of 3: 28.6 µs per loop# method from linkIn [7]: %timeit W = A + A.T - np.diag(A.diagonal())10000 loops, best of 3: 49.8 µs per loop

And with N = 1000

# numpy equivalent to MATLAB:In [6]: %timeit W = np.maximum( A, A.T)100 loops, best of 3: 5.65 ms per loop# method from linkIn [7]: %timeit W = A + A.T - np.diag(A.diagonal())100 loops, best of 3: 11.7 ms per loop