我知道Python列表有一个方法可以返回某个对象的第一个索引:
>>> xs = [1, 2, 3]
>>> xs.index(2)
1
NumPy数组也有类似的东西吗?
我知道Python列表有一个方法可以返回某个对象的第一个索引:
>>> xs = [1, 2, 3]
>>> xs.index(2)
1
NumPy数组也有类似的东西吗?
当前回答
找到了另一个循环解决方案:
new_array_of_indicies = []
for i in range(len(some_array)):
if some_array[i] == some_value:
new_array_of_indicies.append(i)
其他回答
NumPy中有很多操作可以放在一起来完成这个任务。这将返回等于item的元素的下标:
numpy.nonzero(array - item)
然后你可以取列表的第一个元素来得到一个元素。
如果你只需要第一次出现一个值的索引,你可以使用nonzero(或where,在这种情况下相当于相同的东西):
>>> 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
如果需要多个值中的每个值的第一个索引,显然可以重复执行上述操作,但有一个技巧可能更快。下面的代码查找每个子序列的第一个元素的下标:
>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)
注意,它找到了3s的子序列和8s的子序列的开头:
[1, 1, 1, 2, 2, 3, 8, 3, 8, 8]
这和求每个值的第一次出现有点不同。在你的程序中,你可以使用t的排序版本来得到你想要的:
>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
您还可以将NumPy数组转换为list in - air并获取其索引。例如,
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。
从np.where()中选择第一个元素的替代方法是使用生成器表达式和enumerate,例如:
>>> 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)
这种方法的优点是,它在找到第一个匹配后停止检查数组的元素,而np。Where检查所有元素是否匹配。如果在数组的前面有匹配,生成器表达式会更快。
只是添加一个非常高性能和方便的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,)