joechoj
joechoj

Reputation: 1409

Why doesn't a negative array work to reverse numpy.argsort()?

I have a 2D numpy array called 'subset':

array([[  0.00000000e+00,   2.46951219e-03,   4.93902439e-03],
       [             inf,   4.04938272e+02,   2.02469136e+02],
       [  1.77635684e-14,   4.49872050e+01,   1.05094837e+01],
       [  4.33257766e-16,   1.09724890e+00,   2.56328871e-01],
       [  4.85082380e-32,   3.11123702e-01,   1.69792239e-02]])

I'm trying to sort by array 2 (3rd array) in descending order. The following works for ascending order:

>>> subset[:,subset[2,:].argsort()]
array([[  0.00000000e+00,   4.93902439e-03,   2.46951219e-03],
       [             inf,   2.02469136e+02,   4.04938272e+02],
       [  1.77635684e-14,   1.05094837e+01,   4.49872050e+01],
       [  4.33257766e-16,   2.56328871e-01,   1.09724890e+00],
       [  4.85082380e-32,   1.69792239e-02,   3.11123702e-01]])

As you can see, the 3rd array is sorted by increasing order, and the other rows get sorted the same way, preserving the columns as intended.

But when I try to reverse this sorting by doing the same operation on the negative array (thinking it should produce the mirror image of the prior result), it doesn't work as intended.

>>> subset[:,-subset[2,:].argsort()]
array([[  0.00000000e+00,   2.46951219e-03,   4.93902439e-03],
       [             inf,   4.04938272e+02,   2.02469136e+02],
       [  1.77635684e-14,   4.49872050e+01,   1.05094837e+01],
       [  4.33257766e-16,   1.09724890e+00,   2.56328871e-01],
       [  4.85082380e-32,   3.11123702e-01,   1.69792239e-02]])

Why doesn't this work?

Upvotes: 0

Views: 1059

Answers (1)

Paul Panzer
Paul Panzer

Reputation: 53089

The reason it doesn't work is, of course, operator precedence. A pair of parentheses and it does what you want:

subset[:,(-subset[2,:]).argsort()]
# array([[  2.46951219e-03,   4.93902439e-03,   0.00000000e+00],
#        [  4.04938272e+02,   2.02469136e+02,              inf],
#        [  4.49872050e+01,   1.05094837e+01,   1.77635684e-14],
#        [  1.09724890e+00,   2.56328871e-01,   4.33257766e-16],
#        [  3.11123702e-01,   1.69792239e-02,   4.85082380e-32]])

But note that simple reversal is typically faster:

timeit(lambda: subset[:,(-subset[2,:]).argsort()])
# 2.9420917620009277
timeit(lambda: subset[:,subset[2,:].argsort()[::-1]])
# 2.556215071992483

Upvotes: 2

Related Questions