Home > Net >  Numpy index columns
Numpy index columns

Time:04-06

I have a 2d matrix D

array([[1, 1, 8, 8],
       [3, 3, 4, 4],
       [8, 8, 1, 1]])

I would like to find each column's lowest value by indexing it with the amin array:

amin = D.argmin(0)
amin
array([0, 0, 2, 2])

How do I properly index D with amin such that the returned array is array([1, 1, 1, 1])?

CodePudding user response:

You need a combination of expand_dims and take_along_axis

np.take_along_axis(D, np.expand_dims(amin, 0), 0)
Out[]: array([[1, 1, 1, 1]])

This is arguably not the most intuitive formulation, but without going into design philosophy of numpy, I can say it's as "pythonic" as possible in this case.

CodePudding user response:

In [99]: D=np.array([[1, 1, 8, 8],
    ...:        [3, 3, 4, 4],
    ...:        [8, 8, 1, 1]])
In [100]: amin = D.argmin(0)
In [101]: amin
Out[101]: array([0, 0, 2, 2])

What is amin? It has one value per column, but that value is a row index. So what you want is:

In [102]: D[amin[0], 0]
Out[102]: 1
In [103]: D[amin[2], 2]
Out[103]: 1

Or doing all columns at once:

In [104]: D[amin, [0,1,2,3]]
Out[104]: array([1, 1, 1, 1])

Expressions like D[:, amin] try to apply amin to indexing the columns, not the rows. And the slice selects all rows at once. It doesn't pair them up.

May be these versions will make the action clearer:

In [105]: D[[0,0,2,2], [0,1,2,3]]
Out[105]: array([1, 1, 1, 1])
In [106]: [D[i,j] for i,j in zip([0,0,2,2],[0,1,2,3])]
Out[106]: [1, 1, 1, 1]

take_along_axis does the same thing as [104]

In [107]: np.take_along_axis(D, amin[None,:],0)
Out[107]: array([[1, 1, 1, 1]])

It's a bit cleaner if we tell argmin to keepdims (a new feature in v 1.22)

In [108]: amin = D.argmin(0, keepdims=True)
In [109]: amin
Out[109]: array([[0, 0, 2, 2]])
In [110]: np.take_along_axis(D, amin,0)
Out[110]: array([[1, 1, 1, 1]])
  • Related