我知道Python列表有一个方法可以返回某个对象的第一个索引:
>>> xs = [1, 2, 3]
>>> xs.index(2)
1
NumPy数组也有类似的东西吗?
我知道Python列表有一个方法可以返回某个对象的第一个索引:
>>> xs = [1, 2, 3]
>>> xs.index(2)
1
NumPy数组也有类似的东西吗?
当前回答
注意:这是python 2.7版本
您可以使用lambda函数来处理这个问题,它既适用于NumPy数组,也适用于列表。
your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]
import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]
你可以用
result[0]
获取筛选元素的第一个索引。
对于python 3.6,使用
list(result)
而不是
result
其他回答
找到了另一个循环解决方案:
new_array_of_indicies = []
for i in range(len(some_array)):
if some_array[i] == some_value:
new_array_of_indicies.append(i)
对于一维排序数组,使用numpy会更简单、更有效。searchsorted,返回一个NumPy整数(位置)。例如,
arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)
只要确保数组已经排序
还要检查返回的索引i是否包含被搜索的元素,因为searchsorted的主要目标是找到应该插入元素以保持顺序的索引。
if arr[i] == 3:
print("present")
else:
print("not present")
只是添加一个非常高性能和方便的numba替代np。Ndenumerate来查找第一个索引:
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.
这非常快,并且自然地处理多维数组:
>>> arr1 = np.ones((100, 100, 100))
>>> arr1[2, 2, 2] = 2
>>> index(arr1, 2)
(2, 2, 2)
>>> arr2 = np.ones(20)
>>> arr2[5] = 2
>>> index(arr2, 2)
(5,)
这比任何使用np的方法都要快得多(因为它使操作短路)。Where或np. non0。
然而np。Argwhere也可以优雅地处理多维数组(你需要手动将它转换为元组,而且不会短路),但如果没有找到匹配,它就会失败:
>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)
NumPy中有很多操作可以放在一起来完成这个任务。这将返回等于item的元素的下标:
numpy.nonzero(array - item)
然后你可以取列表的第一个元素来得到一个元素。
L.index (x)返回最小的I,使得I是x在列表中第一次出现的索引。
可以放心地假设,Python中的index()函数的实现使它在找到第一个匹配后停止,这将导致最佳的平均性能。
要在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,可以使用第二个参数在未找到元素时返回一个特殊值,例如:
In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)
NumPy中还有其他函数(argmax, where和nonzero)可用于在数组中查找元素,但它们都有一个缺点,即遍历整个数组查找所有出现的元素,因此无法优化以查找第一个元素。还要注意,where和非零返回数组,因此需要选择第一个元素来获取索引。
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),)
时间比较
只是检查对于大型数组,当搜索项位于数组的开头时,使用迭代器的解决方案更快(在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
这是一个开放的NumPy GitHub问题。
参见:Numpy:快速找到第一个值索引