Reputation: 87
import numpy as np
from scipy import linalg as linalg
M = np.array([[1,2],[2,1],[3,4],[4,3]])
Evals, Evecs = linalg.eigh(M.T.dot(M))
EvecShape = Evecs.shape
print Evals
print Evecs
ncols = EvecShape[1]
for i in range(ncols/2):
Evals[i], Evals[ncols-1-i] = Evals[ncols-1-i], Evals[i]
Evecs[:,i], Evecs[:,ncols-1-i] = Evecs[:,ncols-1-i], Evecs[:,i]
print Evals
print Evecs
I want to calculate the eigenvalues and eigenvectors of MT*M and order the eigenvalues in a descending order by swapping corresponding columns. The result printed are below:
[ 2. 58.]
[[-0.70710678 0.70710678]
[ 0.70710678 0.70710678]]
[ 58. 2.]
[[ 0.70710678 0.70710678]
[ 0.70710678 0.70710678]]
It seems that I did swap the elements in Evals. But for Evecs, it is clear that something is wrong. Can anyone tell me what's happening here?
Upvotes: 0
Views: 45
Reputation: 53029
The problem with your code is that when you try to swap the columns you overwrite one with the other before you read out the first. This is because array slices if possible don't copy data but reference the buffer of the array sliced.
To mitigate you can either
.copy()
like so.
Evecs[:,i], Evecs[:,ncols-1-i] = Evecs[:,ncols-1-i], Evecs[:,i].copy()
or
.
Evecs = Evecs[:, ::-1]
Upvotes: 1
Reputation: 527
You are trying to sort eigenvector like two-dimensional array. Not good. Use particular methods. Here below;
import numpy as np
from scipy import linalg as linalg
M = np.array([[1,2],[2,1],[3,4],[4,3]])
Evals, Evecs = linalg.eigh(M.T.dot(M))
print Evals
print Evecs
index = Evals.argsort()[::-1]
Evals= Evals[index]
Evecs = Evecs [:,index]
print Evals
print Evecs
Upvotes: 1