1

I'm looking for a way to find the max value in each row of a 2-dim vector and save the indices of it in another vector. I know that i could do that with this code:

    max_index = np.argmax(vec, axis=1)

Now my problem is when one row has multiple max values it takes the first index of it. Lets assume we have this matrix:

vec = [[1, 0 ,1],
       [1, 2 ,3],
        [0, 5 ,5]]

So i am thinking to replace the index of max with -1 when there is multiple max in one row. At the end max_index should be like this.

max_index = [-1, 2, -1]

Thanks in advance

Milad
  • 125
  • 1
  • 1
  • 8
  • Does this answer your question? [How to return the positions of the maximum value in an array](https://stackoverflow.com/questions/64728506/how-to-return-the-positions-of-the-maximum-value-in-an-array) – fountainhead Nov 26 '20 at 12:20
  • problem I have is with multiple max values in each row. I want to somehow save it that I would know in this row there is multiple max value – Milad Nov 26 '20 at 12:23

3 Answers3

3

Trick: Take the argmax from left and right and check whether they coincide:

L = np.argmax(vec,1)
R = np.argmax(vec[:,::-1],1)
np.where(L+R==len(vec[0])-1,L,-1)

# array([-1,  2, -1])
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
1

Maybe this can solve your issue:

# Creating a copy of vec
vec_without_max = np.copy(vec);

# Remove the max values found before from the new copy
for i in range(np.shape(vec)[0]):
    vec_without_max[i][max_index[i]] = np.iinfo(vec_without_max[i][max_index[i]].dtype).min

# Find the max values on the copy array without the max values of vec
max_index_again = np.argmax(vec_without_max, axis=1)

# Compare the two arrays, if we have the same max value we set the max_index equals to -1
for i in range(np.shape(vec)[0]):
    if vec[i][max_index[i]] == vec[i][max_index_again[i]]:
        max_index[i] = -1

This script returns

max_index = [-1, 2, -1]

for the example you posted but it should work with array of any dimensions.

falfab
  • 13
  • 5
  • @Milad But it uses `for i in range...` which is slow – mathfux Nov 26 '20 at 13:33
  • 1
    I think this will fail if a row contains only negative values. – fountainhead Nov 26 '20 at 17:02
  • @fountainhead you are right. Based on the example I assumed it was composed of only positive numbers. In the case of negative numbers he only need to substitute `vec_without_max[i][max_index[i]] = 0` with `vec_without_max[i][max_index[i]] = np.iinfo(vec_without_max[i][max_index[i]].dtype).min`. – falfab Nov 26 '20 at 18:33
  • @falfab -- Ok. Nice effort. One more thing -- in problems involving `numpy`, try to eliminate explicit loops as much as possible. How exactly the loops may be avoided varies from case to case of course. – fountainhead Nov 26 '20 at 18:40
1

If your original problem is to find the last index of multiple max values then you can follow these approaches

Approach #1

np.argmax((vec.max(axis=1)[...,None] == vec).cumsum(axis=1), axis=1)

Taking -1 as the last index when there are repeated max values in one row, will fail to give the correct index for a row which is like [[1,1,0]].

vec.max(axis=1)gives the max along each row.

vec.max(axis=1)[...,None]converts it into a 2D array.

(vec.max(axis=1)[...,None] == vec) compares each element in each row with the max in each row.

(vec.max(axis=1)[...,None] == vec).cumsum(axis=1) results in cumulative sum whose argmax gives the index of the last max value.

Case1: vec = [[1, 0 ,1], [1, 2 ,3], [0, 5 ,5]], result will be: [2,2,2]

Case2: vec = [[1, 1 ,0], [1, 2 ,3], [0, 5 ,5]], result will be: [1,2,2]

Approach #2

R = np.argmax(vec[:,::-1],1) # Get the index of max from right side
result = vec.shape[1]-1-R 

Here I am reversing the columns and then taking the argmax. After that I am making adjustments to get the correct index

MSS
  • 3,306
  • 1
  • 19
  • 50