1

How can I retrieve a column vector from a 2d array given an indicator column vector?

Suppose I have

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

and

S = np.array([0, 2, 1, 2])

Is there an elegant way to get from X and S the result array([1, 9, 3, 1]), which is equivalent to

np.array([x[s] for x, s in zip(X, S)])
countermode
  • 256
  • 6
  • 20
  • 1
    Does this answer your question? [NumPy selecting specific column index per row by using a list of indexes](https://stackoverflow.com/questions/23435782/numpy-selecting-specific-column-index-per-row-by-using-a-list-of-indexes) – user3483203 Aug 16 '21 at 13:24
  • Yes it does, my search did not return that question – countermode Aug 16 '21 at 14:44

2 Answers2

3

You can achieve this using np.take_along_axis:

>>> np.take_along_axis(X, S[..., None], axis=1)
array([[1],
       [9],
       [3],
       [1]])

You need to make sure both array arguments are of the same shape (or broadcasting can be applied), hence the S[..., None] broadcasting.

Of course your can reshape the returned value with a [:, 0] slice.

>>> np.take_along_axis(X, S[..., None], axis=1)[:, 0]
array([1, 9, 3, 1])

Alternatively you can just use indexing with an arangement:

>>> X[np.arange(len(S)), S[np.arange(len(S))]]
array([1, 9, 3, 1])

I believe this is also equivalent to np.diag(X[:, S]) but with unnecessary copying...

Ivan
  • 24,563
  • 6
  • 44
  • 76
1

For 2d arrays

# Mention row numbers as one list and S which is column number as other
X[[0, 1, 2, 3], S]
# more general
X[np.indices(S.shape), S]

indexing_basics

eroot163pi
  • 1,621
  • 1
  • 8
  • 19