Is there a NumPy function to return the first index of something in an array?

前端 未结 13 1630
萌比男神i
萌比男神i 2020-11-22 05:55

I know there is a method for a Python list to return the first index of something:

>>> l = [1, 2, 3]
>>> l.index(2)
1

Is

相关标签:
13条回答
  • 2020-11-22 06:23

    If you're going to use this as an index into something else, you can use boolean indices if the arrays are broadcastable; you don't need explicit indices. The absolute simplest way to do this is to simply index based on a truth value.

    other_array[first_array == item]
    

    Any boolean operation works:

    a = numpy.arange(100)
    other_array[first_array > 50]
    

    The nonzero method takes booleans, too:

    index = numpy.nonzero(first_array == item)[0][0]
    

    The two zeros are for the tuple of indices (assuming first_array is 1D) and then the first item in the array of indices.

    0 讨论(0)
  • 2020-11-22 06:23

    l.index(x) returns the smallest i such that i is the index of the first occurrence of x in the list.

    One can safely assume that the index() function in Python is implemented so that it stops after finding the first match, and this results in an optimal average performance.

    For finding an element stopping after the first match in a NumPy array use an iterator (ndenumerate).

    In [67]: l=range(100)
    
    In [68]: l.index(2)
    Out[68]: 2
    

    NumPy array:

    In [69]: a = np.arange(100)
    
    In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
    Out[70]: (2L,)
    

    Note that both methods index() and next return an error if the element is not found. With next, one can use a second argument to return a special value in case the element is not found, e.g.

    In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)
    

    There are other functions in NumPy (argmax, where, and nonzero) that can be used to find an element in an array, but they all have the drawback of going through the whole array looking for all occurrences, thus not being optimized for finding the first element. Note also that where and nonzero return arrays, so you need to select the first element to get the index.

    In [71]: np.argmax(a==2)
    Out[71]: 2
    
    In [72]: np.where(a==2)
    Out[72]: (array([2], dtype=int64),)
    
    In [73]: np.nonzero(a==2)
    Out[73]: (array([2], dtype=int64),)
    

    Time comparison

    Just checking that for large arrays the solution using an iterator is faster when the searched item is at the beginning of the array (using %timeit in the IPython shell):

    In [285]: a = np.arange(100000)
    
    In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
    100000 loops, best of 3: 17.6 µs per loop
    
    In [287]: %timeit np.argmax(a==0)
    1000 loops, best of 3: 254 µs per loop
    
    In [288]: %timeit np.where(a==0)[0][0]
    1000 loops, best of 3: 314 µs per loop
    

    This is an open NumPy GitHub issue.

    See also: Numpy: find first index of value fast

    0 讨论(0)
  • 2020-11-22 06:23

    There are lots of operations in NumPy that could perhaps be put together to accomplish this. This will return indices of elements equal to item:

    numpy.nonzero(array - item)
    

    You could then take the first elements of the lists to get a single element.

    0 讨论(0)
  • The numpy_indexed package (disclaimer, I am its author) contains a vectorized equivalent of list.index for numpy.ndarray; that is:

    sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]
    arrays_to_query = [[-5, 0], [1, 0]]
    
    import numpy_indexed as npi
    idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)
    print(idx)   # [2, -1]
    

    This solution has vectorized performance, generalizes to ndarrays, and has various ways of dealing with missing values.

    0 讨论(0)
  • 2020-11-22 06:27

    To index on any criteria, you can so something like the following:

    In [1]: from numpy import *
    In [2]: x = arange(125).reshape((5,5,5))
    In [3]: y = indices(x.shape)
    In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120
    In [5]: pts = hsplit(locs, len(locs[0]))
    In [6]: for pt in pts:
       .....:         print(', '.join(str(p[0]) for p in pt))
    4, 4, 0
    4, 4, 1
    4, 4, 2
    4, 4, 3
    4, 4, 4
    

    And here's a quick function to do what list.index() does, except doesn't raise an exception if it's not found. Beware -- this is probably very slow on large arrays. You can probably monkey patch this on to arrays if you'd rather use it as a method.

    def ndindex(ndarray, item):
        if len(ndarray.shape) == 1:
            try:
                return [ndarray.tolist().index(item)]
            except:
                pass
        else:
            for i, subarray in enumerate(ndarray):
                try:
                    return [i] + ndindex(subarray, item)
                except:
                    pass
    
    In [1]: ndindex(x, 103)
    Out[1]: [4, 0, 3]
    
    0 讨论(0)
  • 2020-11-22 06:31

    You can also convert a NumPy array to list in the air and get its index. For example,

    l = [1,2,3,4,5] # Python list
    a = numpy.array(l) # NumPy array
    i = a.tolist().index(2) # i will return index of 2
    print i
    

    It will print 1.

    0 讨论(0)
提交回复
热议问题