transformar la parte triangular superior / inferior de una matriz simétrica (matriz 2D) en una matriz 1D y devolverla al formato 2D

En esta pregunta se explica cómo acceder a las partes triagulares lower y upper de una matriz dada, por ejemplo:

 m = np.matrix([[11, 12, 13], [21, 22, 23], [31, 32, 33]]) 

Aquí necesito transformar la matriz en una matriz 1D, que se puede hacer haciendo:

 indices = np.triu_indices_from(m) a = np.asarray( m[indices] )[-1] #array([11, 12, 13, 22, 23, 33]) 

Después de hacer muchos cálculos con a , cambiando sus valores, se utilizará para rellenar una matriz 2D simétrica:

 new = np.zeros(m.shape) for i,j in enumerate(zip(*indices)): new[j]=a[i] new[j[1],j[0]]=a[i] 

Volviendo

 array([[ 11., 12., 13.], [ 12., 22., 23.], [ 13., 23., 33.]]) 

¿Hay una mejor manera de lograr esto? Más específicamente, ¿evitando el bucle de Python para reconstruir la matriz 2D?

¿Quieres formar una matriz simétrica? Puede omitir completamente los índices diagonales.

 m=np.array(m) inds = np.triu_indices_from(m,k=1) m[(inds[1], inds[0])] = m[inds] m array([[11, 12, 13], [12, 22, 23], [13, 23, 33]]) 

Creando una matriz simétrica a partir de:

 new = np.zeros((3,3)) vals = np.array([11, 12, 13, 22, 23, 33]) inds = np.triu_indices_from(new) new[inds] = vals new[(inds[1], inds[0])] = vals new array([[ 11., 12., 13.], [ 12., 22., 23.], [ 13., 23., 33.]]) 

Puede usar Rutinas de creación de matrices como numpy.triu , numpy.tril y numpy.diag para crear una matriz simétrica a partir de un triangular. Aquí hay un ejemplo simple de 3×3.

 a = np.array([[1,2,3],[4,5,6],[7,8,9]]) array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) a_triu = np.triu(a, k=0) array([[1, 2, 3], [0, 5, 6], [0, 0, 9]]) a_tril = np.tril(a, k=0) array([[1, 0, 0], [4, 5, 0], [7, 8, 9]]) a_diag = np.diag(np.diag(a)) array([[1, 0, 0], [0, 5, 0], [0, 0, 9]]) 

Suma la transposición y resta la diagonal:

 a_sym_triu = a_triu + a_triu.T - a_diag array([[1, 2, 3], [2, 5, 6], [3, 6, 9]]) a_sym_tril = a_tril + a_tril.T - a_diag array([[1, 4, 7], [4, 5, 8], [7, 8, 9]])