classificar autovalores e autovetores associados após usar numpy.linalg.eig em python

101

Estou usando numpy.linalg.eig para obter uma lista de valores e vetores próprios:

A = someMatrixArray
from numpy.linalg import eig as eigenValuesAndVectors

solution = eigenValuesAndVectors(A)

eigenValues = solution[0]
eigenVectors = solution[1]

Gostaria de classificar meus autovalores (por exemplo, do mais baixo para o mais alto), de uma forma que sei qual é o autovetor associado após a classificação.

Não estou encontrando nenhuma maneira de fazer isso com funções Python. Existe alguma maneira simples ou tenho de codificar minha versão de classificação?

Jorge Leitão
fonte

Respostas:

161

Use numpy.argsort . Ele retorna os índices que seriam usados ​​para classificar a matriz.

import numpy as np
import numpy.linalg as linalg

A = np.random.random((3,3))
eigenValues, eigenVectors = linalg.eig(A)

idx = eigenValues.argsort()[::-1]   
eigenValues = eigenValues[idx]
eigenVectors = eigenVectors[:,idx]

Se os valores próprios forem complexos, a ordem de classificação é lexicográfica (ou seja, os números complexos são classificados de acordo com sua parte real primeiro, com laços quebrados por sua parte imaginária).

unutbu
fonte
27
A propósito, é mais comum classificar do maior para o menor autovalor. apenas use: idx = eigenValues.argsort()[::-1].
Carl F.
5
para obter os k maiores autovalores k = 2 idx = eigenValues.argsort () [- k:] [:: - 1]
mrgloom
3
Para k = 1, pode-se usareigenVectors[:, eigenValues.argmax()]
utapyngo
1
@MaxNoe: De acordo com os documentos , "Os valores próprios não são necessariamente ordenados."
unutbu
2
Ah, eu estava usando eigh: os autovalores em ordem crescente, cada um repetido de acordo com sua multiplicidade.
MaxNoe
6

A resposta acima por unutbu é muito nítida e concisa. Mas, aqui está uma outra maneira de fazer isso mais geral e pode ser usada para listas também.

eval, evec =  sp.eig(A)
ev_list = zip( eval, evec )
ev_list.sort(key=lambda tup:tup[0], reverse=False)
eval, evec = zip(*ev_list)

Este tup [0] é o valor próprio com base no qual a função de classificação classificará a lista.

reverse = False é para ordem crescente.

ShikharDua
fonte
2

O pedaço de código do ubuntu não funciona no meu Python 3.6.5. Isso leva a erros em tempo de execução. Então, eu refatorei seu código para este que funciona bem em meus casos de teste:

import numpy as np
from numpy import linalg as npla
#
def eigen(A):
    eigenValues, eigenVectors = npla.eig(A)
    idx = np.argsort(eigenValues)
    eigenValues = eigenValues[idx]
    eigenVectors = eigenVectors[:,idx]
    return (eigenValues, eigenVectors)
std.approach
fonte