0

I have calculated the eigenvalues of a 5x5 jacobian matrix while looping over a parameter R.

I get both real and complex eigenvalues as expected, but all are given in complex form. The issue I am having is that numpy.sort sorts these values by the real part of each eigenvalue which is useful to a point, but the real part of each eigenvalue is either increasing/decreasing as I vary R.

Thus there becomes a point where I need to sort by imaginary part also to keep each eigenvalue in the same entry in the output array. The picture below shows what I mean. I get 3 real eigenvalues displayed in positions 2, 3 and 4 in the array jumping to positions 0,1 and 4. How can I sort by imaginary part? I have added my code below. Eigenvalues switching column

import numpy.linalg as la

for a,b,c,d,e,f in zip(T_S, T_C, S_S, S_C, w, R):

    eigvals = la.eigvals(np.array([[-f, e, 0, 0, b], 
                                   [-e, -f, 0, 0, -a], 
                                   [0, 0, -f, e, d],
                                   [0, 0, -e, -d, -c], 
                                   [-1/(2*F), 0, D/(2*F), 0, -1/F]]))

    eigvals = np.sort(eigvals)
    print(np.round(eigvals, decimals = 3))

EDIT: Upon thinking about this, I don't think sorting is going to help me here. Thanks to those who answered.

I wish to keep the purely real eigenvalue in the same position in the array for each iteration. The sorting is precisely what is making it change position.

  for i = 4.2 eigvals = [-0.33-4.16j -0.33+4.16j -0.33+0.j    0.  -4.2j   0. +4.2j ]
  for i = 4.3 eigvals = [-0.35+0.j   -0.33-4.26j -0.33+4.26j  0.  -4.3j   0.  +4.3j ]

In the i = 4.2 case the real root is in position 2 but for i = 4.3 the real part decreases so np.sort moves it to position 0.

I am not sure there is an easy way around this but any suggestions would be great.

  • 1
    Does this answer your question? [Sort a list by multiple attributes?](https://stackoverflow.com/questions/4233476/sort-a-list-by-multiple-attributes) – Chrispresso Mar 31 '20 at 16:13
  • I am not sure I understand the input and the desired output. Could you please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) where you explain input / output / desired output? – DarK_FirefoX Mar 31 '20 at 16:35

2 Answers2

1

Your question is not very clear but I'll try to answer at least this key element:

How can I sort by imaginary part ?

You can simply exchange temporarily the real and imag parts:

import numpy as np
a = np.array([-1+1j, 0-1j, 1])

def xch_real_imag(arr):
    return a.imag + 1j * a.real

print(a)
imag_sorted = xch_real_imag(np.sort(xch_real_imag(a)))
print(imag_sorted)

yields

[-1.+1.j  0.-1.j  1.+0.j]
[ 1.-1.j -1.+0.j  0.+1.j]

If you need a more precise answer about your case, please edit your question with a reproducible example, that will help the community try to help you.

smarie
  • 4,568
  • 24
  • 39
0

I am assuming you want to sort an np.array() of complex numbers first by real part and then imaginary part. At least, I think that's the main thing on your question.

Say you have:

import numpy as np

a = np.array([3+4j, 1+2j, 3+3j, 3+2j])

Numpy documentation on numpy.sort() states:

The sort order for complex numbers is lexicographic. If both the real and imaginary parts are non-nan then the order is determined by the real parts except when they are equal, in which case the order is determined by the imaginary parts.

So, there you go, numpy takes care of that for you, no need to fancy operations. For the example above, you can do:

print(a)
x = np.sort(a)
print(x)

Outputs:

[3.+4.j 1.+2.j 3.+3.j 3.+2.j] # prior to sorting

[1.+2.j 3.+2.j 3.+3.j 3.+4.j] # sorted

Note how the 3 last items have the same real part (3), and three different imaginary partas (2, 3, 4) and how they are sorted in increasing order.

DarK_FirefoX
  • 887
  • 8
  • 20