You can't exactly vectorize np.argmax
because you have a random subset size every time. What you can do though, is speed up the computation pretty dramatically with sorting. Sorting the image once will create a single allocation, while masking the image at every step will create a temporary array for the mask and for the extracted elements. With a sorted image, you can just apply np.searchsorted
to get the sizes:
a_sorted = np.sort(a.ravel())
indices = np.searchsorted(a_sorted, b, side='right')
You still need a loop to do the sampling, but you can do something like
samples = np.array([a_sorted[np.random.randint(i)] for i in indices])
Getting x-y coordinates instead of sample values is a bit more complicated with this system. You can use np.unravel_index
to get the indices, but first you must convert form the reference frame of a_sorted
to a.ravel()
. If you sort using np.argsort
instead of np.sort
, you can get the indices in the original array. Fortunately, np.searchsorted
supports this exact scenario with the sorter
parameter:
a_ind = np.argsort(a, axis=None)
indices = np.searchsorted(a.ravel(), b, side='right', sorter=a_ind)
r, c = np.unravel_index(a_ind[[np.random.randint(i) for i in indices]], a.shape)
r
and c
are the same size as b
, and correspond to the row and column indices in a
of each selection based on b
. The index conversion depends on the strides in your array, so we'll assume that you're using C order, as 90% of arrays will do by default.
Complexity
Let's say b
has size M
and a
has size N
.
Your current algorithm does a linear search through each element of a
for each element of b
. At each iteration, it allocates a mask for the matching elements (N/2
on average), and then a buffer of the same size to hold the masked choices. This means that the time complexity is on the order of O(M * N)
and the space complexity is the same.
My algorithm sorts a
first, which is O(N log N)
. Then it searches for M
insertion points, which is O(M log N)
. Finally, it selects M
samples. The space it allocates is one sorted copy of the image and two arrays of size M
. It is therefore of O((M + N) log N)
time complexity and O(M + N)
in space.