2

Imagine you have a 3d array like e.g.

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

A.shape (3, 2, 2)

array([[[1, 2],
        [2, 3]],

       [[3, 4],
        [1, 2]],

       [[2, 3],
        [3, 4]]])

Now, if I want to get the indices of maxima along the first dimension this is easy as

A.argmax(axis=0)

array([[1, 1],
       [2, 2]])

How do I do the same for a 4d array finding the maximum along the first two dimensions?

Example 4d array

np.random.randint(0, 9,[2,3,2,2])

B = array([[[[5, 4],
         [3, 8]],

        [[3, 5],
         [0, 4]],

        [[0, 1],
         [3, 0]]],


       [[[0, 2],
         [7, 3]],

        [[7, 3],
         [8, 0]],

        [[8, 3],
         [2, 7]]]])

B.shape (2, 3, 2, 2)

In that case, the output should still be a (2, 2) matrix, but each cell containing a tuple of the maximum index of dimension 0 and dimension 1, i.e.

Example output

array([[(1, 2), (0, 1)],
       [(1, 1), (0, 0)]])

Solution

As correctly pointed out by @hpaulj the solution to this problem lies in calling

idx = B.reshape(6,2,2).argmax(axis=0)
2d_indices = np.unravel_index(idx,(2,3))

However, this way the ordering is a bit different to what I expected (and outlined in my question above). To get the output exactly as above, just add

list_of_tuples = [a for a in zip(2d_indices[0].flatten(), 2d_indices[1].flatten())]
np.array(list_of_tuples).reshape(3, 3, -1)

It looks a bit cumbersome to me and there may be a more direct way of getting there, but I still want to post it for the sake of completeness :)

2
  • 3
    Will you please show a sample of your 4D array? Commented Dec 10, 2021 at 20:11
  • i have added a 4d example and changed the output that it reflects the desired outcome Commented Dec 10, 2021 at 20:22

1 Answer 1

2

argmax only accepts scalar axis values (some other functions allow tuples). But we can reshape B:

In [18]: B.reshape(6,2,2).argmax(axis=0)
Out[18]: 
array([[5, 1],
       [4, 0]])

and convert those back to 2d indices:

In [21]: np.unravel_index(_18,(2,3))
Out[21]: 
(array([[1, 0],
        [1, 0]]),
 array([[2, 1],
        [1, 0]]))

those values could be reordered in various ways, for example:

In [23]: np.transpose(_21)
Out[23]: 
array([[[1, 2],
        [1, 1]],

       [[0, 1],
        [0, 0]]])
Sign up to request clarification or add additional context in comments.

4 Comments

similar (but not identical) output can be produced by B.argmax(axis=1)[::-1]
Thank you @hpaulj! that's very helpful! What I don't understand though is the ordering of the outcome. After you call np.transpose(_21) the upper half of the matrix is ordered as I expect it. The lower part, however, not. I did the same for a 3x3 matrix and also the ordering is mixed up. I'm trying to solve the riddle, however, if you can provide an answer I gladly accept your response!
Out[21] is a pair of arrays that can be used on B, the first for the first dimension, the 2nd for 2nd dimension. Your (1,2) is the index for one subarray. May I should be asking you where/why did you choose that layout? How will you use it? It doesn't work directly to index B. Mine does.
Yep you're right, I also just realized this!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.