Pepper
Pepper

Reputation: 139

Numpy: Find index of second highest value in each row of an ndarray

I have a [10,10] numpy.ndarray. I am trying to get the index the second highest number in each row. So for the array:

[101   0   1   0   0   0   1   1   2   0]
[  0 116   1   0   0   0   0   0   1   0]
[ 1  4 84  2  2  0  2  4  6  1]
[ 0  2  0 84  0  6  0  2  3  0]
[ 0  0  1  0 78  0  0  2  0 11]
[ 2  0  0  1  1 77  5  0  2  0]
[ 1  2  1  0  1  2 94  0  1  0]
[ 0  1  1  0  0  0  0 96  0  4]
[ 1  5  4  3  1  3  0  1 72  4]
[ 0  1  0  0  3  2  0  7  0 82]

Expected result: [8, 2, 8, 5, 9, ...]

Any suggestions?

Upvotes: 7

Views: 9923

Answers (3)

Andy L.
Andy L.

Reputation: 25239

Use argpartition may be faster than argsort

In [167]: n = 2

In [168]: arr.argpartition(-n)[:,-n]
Out[168]: array([8, 8, 8, 5, 9, 6, 1, 9, 1, 7], dtype=int32)

Upvotes: 2

s3dev
s3dev

Reputation: 9681

The amazing numpy.argsort() function makes this task really simple. Once the sorted indices are found, get the second to last column.

m = np.array([[101,   0,   1,   0,   0,   0,   1,   1,   2,   0],
              [  0, 116,   1,   0,   0,   0,   0,   0,   1,   0],
              [  1,   4,  84,   2,   2,   0,   2,   4,   6,   1],
              [  0,   2,   0,  84,   0,   6,   0,   2,   3,   0],
              [  0,   0,   1,   0,  78,   0,   0,   2,   0,  11],
              [  2,   0,   0,   1,   1,  77,   5,   0,   2,   0],
              [  1,   2,   1,   0,   1,   2,  94,   0,   1,   0],
              [  0,   1,   1,   0,   0,   0,   0,  96,   0,   4],
              [  1,   5,   4,   3,   1,   3,   0,   1,  72,   4],
              [  0,   1,   0,   0,   3,   2,   0,   7,   0,  82]])

# Get index for the second highest value.
m.argsort()[:,-2]

Output:

array([8, 8, 8, 5, 9, 6, 5, 9, 1, 7], dtype=int32)

Upvotes: 15

Gabriel Ayres
Gabriel Ayres

Reputation: 19

I got confused about some things, like:

1 - If the highest number repeats, would you consider it as the second highest number?

2 - If the second highest number repeats, would you like to know all its positions in the array or just the first appearance?

Anyway, there is my solution for my interpretation:

import numpy as np

my_array = np.array([[101 ,0 ,1 ,0 ,0 ,0 ,1 ,1 ,2 ,0],
[ 0 ,116 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,0],
[ 1 ,4 ,84 ,2 ,2 ,0 ,2 ,4 ,6 ,1],
[ 0 ,2 ,0 ,84 ,0 ,6 ,0 ,2 ,3 ,0],
[ 0 ,0 ,1 ,0 ,78 ,0 ,0 ,2 ,0 ,11],
[ 2 ,0 ,0 ,1 ,1 ,77 ,5 ,0 ,2 ,0],
[ 1 ,2 ,1 ,0 ,1 ,2 ,94 ,0 ,1 ,0],
[ 0 ,1 ,1 ,0 ,0 ,0 ,0 ,96 ,0 ,4],
[ 1 ,5 ,4 ,3 ,1 ,3 ,0 ,1 ,72 ,4],
[ 0 ,1 ,0 ,0 ,3 ,2 ,0 ,7 ,0 ,82]])

result = []

for row in my_array:
    second = np.sort(row)[-2] #Finds the second highest number
    i = np.where(row == second) #Looks for where the condition is true
    result.append(i[0][0]) #Appends the first occurence

Upvotes: 1

Related Questions