1

I have integer arrays of the type:

import numpy as np

seed_idx = np.asarray([[0, 1],
                       [1, 2],
                       [2, 3],
                       [3, 4]], dtype=np.int_)

target_idx = np.asarray([[2,9,4,1,8],
                         [9,7,6,2,4],
                         [1,0,0,4,9],
                         [7,1,2,3,8]], dtype=np.int_)

For each row of target_idx, I want to select the elements whose indices are not the ones in seed_idx. The resulting array should thus be:

[[4,1,8],
 [9,2,4],
 [1,0,9],
 [7,1,2]]

In other words, I want to do something similar to np.take_along_axis(target_idx, seed_idx, axis=1), but excluding the indices instead of keeping them.

What is the most elegant way to do this? I find it surprisingly annoying to find something neat.

2 Answers 2

1

You can mask out the values you don't want with np.put_along_axis and then index the others:

>>> np.put_along_axis(target_idx, seed_idx, -1, axis=1)
>>> target_idx[np.where(target_idx != -1)].reshape(len(target_idx), -1)
array([[4, 1, 8],
       [9, 2, 4],
       [1, 0, 9],
       [7, 1, 2]])

If -1 is a valid value, use target_idx.min() - 1.

Sign up to request clarification or add additional context in comments.

5 Comments

That's the solution I had come to as well, but it still feels quite clumsy. I'll wait to see if there are a few more suggestions and if not I'll accept this one. Thanks for the tip for the valid value.
@Ben Is your seed_idx always going to be this predictable shape (it's like a parallelogram)? If so, some stride tricks might be possible.
In general, seed_idx will always have shape (..., M) and target_idx will always have shape (..., N), where N > M and where the (...,) are the same batch shape in both cases.
I don't mean the array dimensions, I mean that rhomboid/staircase geometrical shape of the masked out values ("shape" was a confusing word to use in hindsight).
Ah no, that was just for example's sake, sorry!
1

I thought about using put_along_axis on a mask, but I settled on raveling and deleting with linear indexing.

m, n = seed_idx.shape
i = seed_idx + np.arange(m)[:, np.newaxis]*n  # calculate linear indices
out = np.delete(target_idx.ravel(), i)  # remove them
out = out.reshape(m, -1)  # reshape

1 Comment

That's a nice one. You could show the intermediate i to demonstrate the logic ;)

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.