Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy finding element index in another array

I have an array/set with unique positive integers, i.e.

>>> unique = np.unique(np.random.choice(100, 4, replace=False))

And an array containing multiple elements sampled from this previous array, such as

>>> A = np.random.choice(unique, 100)

I want to map the values of the array A to the position of which those values occur in unique.

So far the best solution I found is through a mapping array:

>>> table = np.zeros(unique.max()+1, unique.dtype)
>>> table[unique] = np.arange(unique.size)

The above assigns to each element the index on the array, and thus, can be used later to map A through advanced indexing:

>>> table[A]
array([2, 2, 3, 3, 3, 3, 1, 1, 1, 0, 2, 0, 1, 0, 2, 1, 0, 0, 2, 3, 0, 0, 0,
       0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 3, 0, 1, 3, 0, 1, 2, 3, 3, 3, 3, 1,
       3, 0, 1, 2, 0, 0, 2, 3, 1, 0, 3, 2, 3, 3, 3, 1, 1, 2, 0, 0, 2, 0, 2,
       3, 1, 1, 3, 3, 2, 1, 2, 0, 2, 1, 0, 1, 2, 0, 2, 0, 1, 3, 0, 2, 0, 1,
       3, 2, 2, 1, 3, 0, 3, 3], dtype=int32)

Which already gives me the proper solution. However, if the unique numbers in unique are very sparse and large, this approach implies creating a very large table array just to store a few numbers for later mapping.

Is there any better solution?

NOTE: both A and unique are sample arrays, not real arrays. So the question is not how to generate positional indexes, it is just how to efficiently map elements of A to indexes in unique, the pseudocode of what I'd like to speedup in numpy is as follows,

B = np.zeros_like(A)
for i in range(A.size):
    B[i] = unique.index(A[i])

(assuming unique is a list in the above pseudocode).

like image 676
Imanol Luengo Avatar asked May 26 '16 14:05

Imanol Luengo


People also ask

How do you get the positions where elements of two arrays match NumPy?

import numpy as np A = np. array([[1, 1], [2, 2]]) B = np. array([[1, 1], [2, 2]]) print(A == B) In this resulting matrix, each element is a result of a comparison of two corresponding elements in the two arrays.

How do you find the index of an element in an array?

To find the position of an element in an array, you use the indexOf() method. This method returns the index of the first occurrence the element that you want to find, or -1 if the element is not found.


3 Answers

The table approach described in your question is the best option when unique if pretty dense, but unique.searchsorted(A) should produce the same result and doesn't require unique to be dense. searchsorted is great with ints, if anyone is trying to do this kind of thing with floats which have precision limitations, consider something like this.

like image 164
Bi Rico Avatar answered Oct 19 '22 01:10

Bi Rico


You can use standard python dict with np.vectorize

inds = {e:i for i, e in enumerate(unique)}
B = np.vectorize(inds.get)(A)
like image 26
hilberts_drinking_problem Avatar answered Oct 19 '22 02:10

hilberts_drinking_problem


The numpy_indexed package (disclaimer: I am its author) contains a vectorized equivalent of list.index, which does not require memory proportional to the max element, but only proportional to the input itself:

import numpy_indexed as npi
npi.indices(unique, A)

Note that it also works for arbitrary dtypes and dimensions. Also, the array being queried does not need to be unique; the first index encountered will be returned, the same as for list.

like image 2
Eelco Hoogendoorn Avatar answered Oct 19 '22 00:10

Eelco Hoogendoorn