有没有一个Numpy函数返回数组中的东西的第一个索引?

我知道有一个Python列表返回的东西的第一个索引的方法

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

有没有像那样的数组?

是的,下面是给定一个Numpy数组,数组和要search的值的项目的答案。

 itemindex = numpy.where(array==item) 

结果是首先包含所有行索引的元组,然后是所有列索引。

例如,如果数组是两个维度,它包含您的项目在两个位置然后

 array[itemindex[0][0]][itemindex[1][0]] 

将等于你的物品,所以会

 array[itemindex[0][1]][itemindex[1][1]] 

numpy.where

如果你需要只有一个值的第一次出现的索引,那么你可以使用nonzero (或者在这种情况下相当于相同的东西):

 >>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8]) >>> nonzero(t == 8) (array([6, 8, 9]),) >>> nonzero(t == 8)[0][0] 6 

如果你需要多个值中的每一个的第一个索引,你可以重复做同样的事情,但有一个技巧可能会更快。 以下find每个子序列的第一个元素的索引:

 >>> nonzero(r_[1, diff(t)[:-1]]) (array([0, 3, 5, 6, 7, 8]),) 

注意它find了3s的两个子序列和8s的两个子序列的开始:

[1,1,2,2,3,8,3,8,8]

因此,与查找每个值的第一个匹配项稍有不同。 在你的程序中,你可能能够使用t的sorting版本来得到你想要的:

 >>> st = sorted(t) >>> nonzero(r_[1, diff(st)[:-1]]) (array([0, 3, 5, 7]),) 

你也可以转换一个Numpy数组来列表并获得其索引。 例如

 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 

将打印1。

如果你打算把它作为其他的索引,如果数组是可以广播的,你可以使用布尔值索引。 你不需要明确的索引。 要做到这一点绝对最简单的方法是简单地根据一个真值进行索引。

 other_array[first_array == item] 

任何布尔操作的作品:

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

非零方法也需要布尔运算符:

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

这两个零是索引元组(假设first_array是1D),然后是索引数组中的第一个元素。

根据任何标准进行索引,您可以如下所示:

 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 

这里有一个快速的函数来做list.index()所做的事情,除非没有findexception,否则不会引发exception。 要小心 – 在大型数组上这可能非常慢。 如果你想把它作为一个方法来使用的话,你也许可以将它们应用到数组上。

 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] 

在numpy中有很多的操作,也许可以放在一起来完成这个。 这将返回元素的索引等于项目:

 numpy.nonzero(array - item) 

然后,您可以将列表的第一个元素获取一个元素。

只需要添加一个非常高效和方便的numba选项来find第一个索引:

 from numba import njit import numpy as np @njit def index(array, item): for idx, val in np.ndenumerate(array): if val == item: return idx # If no item was found return None, other return types might be a problem due to # numbas type inference. 

这是相当快的, 自然地处理multidimensional array

 >>> arr1 = np.ones((100, 100, 100)) >>> arr1[2, 2, 2] = 2 >>> index(arr1, 2) (2, 2, 2) >>> arr2 = np.ones(20) >>> arr2[5] = 10 >>> index(arr2, 2) (5,) 

这可以比任何使用np.wherenp.nonzero方法快得多 (因为它是短路操作)。


然而, np.argwhere也可以优雅地处理multidimensional array(你需要手动把它转换成一个元组而不是短路),但是如果找不到匹配就会失败:

 >>> tuple(np.argwhere(arr1 == 2)[0]) (2, 2, 2) >>> tuple(np.argwhere(arr2 == 2)[0]) (5,) 

对于一维数组,我推荐np.flatnonzero(array == value)[0] ,它等同于np.nonzero(array == value)[0][0]np.where(array == value)[0][0]但避免拆箱1元素元组的丑陋。

l.index(x)返回最小的i ,使得i是列表中第一个x的索引。

人们可以安全地假定Python中的index()函数被实现,以便在find第一个匹配之后停止,并且这导致最佳的平均性能。

为了查找在numpy数组中第一次匹配之后停止的元素,使用迭代器( ndenumerate )。

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

Numpy数组:

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

请注意,如果找不到元素,那么index()next返回一个错误。 next一个可以使用第二个参数来返回一个特殊的值,如果没有find元素,例如

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

在numpy( argmaxwhereargmaxwhere还有其他的函数可以用来在数组中寻找一个元素,但是他们都有通过整个数组寻找所有事件的缺点,因此没有被优化用于寻找第一个元素。 还要注意, wherenonzero返回数组,所以你需要select第一个元素来获取索引。

 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),) 

时间比较

只需检查大数组,使用迭代器的解决scheme在search的项目位于数组的开头时会更快(在IPython shell中使用%timeit

 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 

这是一个开放的Nuby Github问题 。

另请参阅: Numpy:快速find第一个索引值

从np.where()中select第一个元素的另一种方法是与枚举一起使用生成器expression式,例如:

 >>> import numpy as np >>> x = np.arange(100) # x = array([0, 1, 2, 3, ... 99]) >>> next(i for i, x_i in enumerate(x) if x_i == 2) 2 

对于二维数组,人们可以这样做:

 >>> x = np.arange(100).reshape(10,10) # x = array([[0, 1, 2,... 9], [10,..19],]) >>> next((i,j) for i, x_i in enumerate(x) ... for j, x_ij in enumerate(x_i) if x_ij == 2) (0, 2) 

这种方法的优点是在find第一个匹配之后停止检查数组的元素,而np.where则检查所有匹配的元素。 如果在数组的早期匹配,则生成器expression式会更快。

numpy_indexed包(免责声明,我是它的作者)包含一个向量化的numpy.ndarray的list.index相当于; 那是:

 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] 

这个解决scheme具有向量化的性能,可以推广到ndarrays,并且有各种处理缺失值的方法。