Amelio Vazquez-Reina
Amelio Vazquez-Reina

Reputation: 96360

np.argsort with support for ties

Say we define a function for doing argsort with support for ties as described in this solution:

def argsort_with_support_for_ties(a):
  rnd_array = np.random.random(a.size)
  return np.lexsort((rnd_array,a))

We test it on:

input  = np.array([5.5, 3.5, 2.0, 2.0, 7.0, 7.0, 7.0, 3.5, 6.5, 6.5, 6.5, 9.0])
output = argsort_with_support_for_ties(input)

with he following result:

> np.stack([input, output], axis=0).T

array([[  5.5,   3. ],
       [  3.5,   2. ],
       [  2. ,   1. ],
       [  2. ,   7. ],
       [  7. ,   0. ], <--- A
       [  7. ,  10. ], <--- B
       [  7. ,   9. ],
       [  3.5,   8. ],
       [  6.5,   5. ],
       [  6.5,   4. ],
       [  6.5,   6. ],
       [  9. ,  11. ]])

Note how entries A and B shared the same input value (7), but ended up in vastly different locations 0 and 10.

This is not what I was hoping to get. A more acceptable answer would have been:

output  = np.array([4, 2, 1, 0, 8, 9, 10, 3, 5, 6, 7, 11])

So what failed above with argsort_with_support_for_ties?

Upvotes: 1

Views: 530

Answers (1)

user6655984
user6655984

Reputation:

I understand that you want to rank the elements so that the tiebreaking is random. For this you just need to invert the permutation that you got from lexsort:

output = np.argsort(np.lexsort((rnd_array,a)))

My output (which is not identical to yours because of randomness):

array([ 4,  3,  0,  1, 10,  9,  8,  2,  7,  5,  6, 11])

Upvotes: 1

Related Questions