1

Given an upper triangular matrix (or lower triangular)

A = np.array([[1, 2, 3],
              [0, 4, 5],
              [0, 0, 6]]
             )

I would like to sort its values from largest to smallest, keeping track of the ij indices, so for instance in this matrix I would want something like

6, (2,2)
5, (1,2)
4, (1,1)
3, (0,2)
2, (0,1)
1, (0,0)

This simple example uses a matrix with integers, but it should handle floats as well as arbitrarily large matrices, generally between 10x10 and 40x40. Speed is not very important, it is a one time operation. Also, it need not be upper or lower, the matrix is symmetrical, so I can simply fill in the opposite triangle if that is easier.

I have tried np.argsort() but that just gives

array([[0, 1, 2],
       [0, 1, 2],
       [0, 1, 2]], dtype=int64)

which is to say, it sorts each row independently. This doesn't help much since I don't want a list of the largest elements in each row, it could be that one row has all of the largest values.

Wesley
  • 113
  • 5
  • 2
    `np.dstack(np.unravel_index(np.argsort(-A.ravel()), (3, 3)))` ? source : https://stackoverflow.com/a/30577520/12502959 – python_user Aug 25 '21 at 11:53
  • @python_user I think that works, it orders it in reverse, but that isn't a big deal – Wesley Aug 25 '21 at 11:58
  • 1
    I just edited it to order in the way you want – python_user Aug 25 '21 at 11:58
  • @python_user I guess you might as well post this one-liner as an answer. – Stef Aug 25 '21 at 13:11
  • @Stef other than the making the array negative, I did not really change anything from the source, if anything, this can be a dupe of that, but my numpy skills are not good enough to confidently mark it a dupe – python_user Aug 25 '21 at 13:14
  • 1
    @python_user So you don't want to "claim credit" by making it your answer, which is very honest of you; still, comments tend to disappear, and this answers the question. If anyone with a similar question finds this page in the future because of a search engine, and it is neither marked as a duplicate nor answered, they'll be disappointed. Note that you can tick the "community answer" box when writing an answer if you really don't want credit. – Stef Aug 25 '21 at 13:22

1 Answers1

2

You can use the code shown in this answer, (provided you negate your array) to perform a "2d argsort".

>>> A = np.array([[1, 2, 3], [0, 4, 5], [0, 0, 6]])

>>> A
array([[1, 2, 3],
       [0, 4, 5],
       [0, 0, 6]])

>>> np.dstack(np.unravel_index(np.argsort(-A.ravel()), (3, 3)))
array([[[2, 2],
        [1, 2],
        [1, 1],
        [0, 2],
        [0, 1],
        [0, 0],
        [1, 0],
        [2, 0],
        [2, 1]]], dtype=int64)

PS : If any user who is confident of their numpy skills feel this should be a dupe do mark it, in the mean time this will be a "Community Wiki" as suggested by Stef in the comments.

python_user
  • 5,375
  • 2
  • 13
  • 32