Numpy等效于list.index

时间:2011-02-23 22:30:26

标签: python numpy

在一个被多次调用的低级函数中,我需要做相当于python的list.index,但是需要一个numpy数组。函数需要在找到第一个值时返回,否则引发ValueError。类似的东西:

>>> a = np.array([1, 2, 3])
>>> np_index(a, 1)
0
>>> np_index(a, 10)
Traceback (most recent call last):    
  File "<stdin>", line 1, in <module>
ValueError: 10 not in array

如果可能的话,我想避免使用Python循环。 np.where不是一个选项,因为它总是遍历整个数组;一旦找到第一个索引,我需要停止的东西。


编辑:与问题相关的一些更具体的信息。

  • 大约90%的时间,我正在搜索的索引是数组的前1/4到1/2。因此,这里可能存在2-4倍的加速因素。其余10%的时间值都不在数组中。

  • 我已经对事情进行了分析,对np.where的调用是瓶颈,至少占总运行时间的50%。

  • 提出ValueError并不重要;它只需要返回一些显然表明该值不在数组中的东西。

我可能会按照建议在Cython中编写解决方案。

6 个答案:

答案 0 :(得分:8)

请参阅我对OP的问题的评论,但总的来说,我会做以下事情:

import numpy as np
a = np.array([1, 2, 3])
np.min(np.nonzero(a == 2)[0])

如果您要查找的值不在数组中,则会得到ValueError,原因如下:

ValueError: zero-size array to ufunc.reduce without identity

因为你试图获取空数组的最小值。

我会分析这段代码并查看它是否是一个真正的瓶颈,因为通常当numpy使用内置函数而不是显式python循环搜索整个数组时,它相对较快。当发现第一个值时,坚持停止搜索可能在功能上无关紧要。

答案 1 :(得分:3)

如果您的numpy数组是1d数组,可以尝试这样:

a = np.array([1, 2, 3])
print a.tolist().index(2)
>>> 1

如果不是1d,您可以搜索数组:

a = np.array([[1, 2, 3],[2,5,6],[0,0,2]])
print a[0,:].tolist().index(2)
>>> 1

print a[1,:].tolist().index(2)
>>> 0

print a[2,:].tolist().index(2)
>>> 2

答案 2 :(得分:1)

我能找到的最接近你要求的是非零。这可能听起来很奇怪,但是文档看起来可能会产生预期的结果。

http://www.scipy.org/Numpy_Example_List_With_Doc#nonzero

特别是这部分:

  

a.nonzero()

     

返回非零元素的索引。

     

有关完整文档,请参阅numpy.nonzero

     

另见

     

numpy.nonzero:等效函数

>>> from numpy import *
>>> y = array([1,3,5,7])
>>> indices = (y >= 5).nonzero()
>>> y[indices]
array([5, 7])
>>> nonzero(y)                                # function also exists
(array([0, 1, 2, 3]),)

您可能也对(http://www.scipy.org/Numpy_Example_List_With_Doc#where)感兴趣。

答案 3 :(得分:1)

您可以在Cython中编码,只需从Python脚本导入即可。无需将整个项目迁移到Cython中。

# paste into: indexing.pyx
def index(long[:] lst, long value):
    cdef int i
    for i in range(len(lst)):
        if lst[i] == value:
            return i
    raise ValueError

# import in your .py code
import pyximport
pyximport.install()
from indexing import index

# example
from numpy import zeros
a = zeros(10**6, int)
a[-1] = 1

index(a, 1)
Wall time: 6.07 ms
999999

index(a, 0)
Wall time: 38.1 µs
0

答案 4 :(得分:0)

我遇到这个问题的唯一一次,将numpy数组转换为列表就足够了:

a = numpy.arange(3)
print(list(a).index(2))

>>> 2

答案 5 :(得分:-1)

NumPy的searchsorted与列表的索引非常相似,不同之处在于它需要一个排序的数组并且行为更加数字化。最大的区别在于您不需要精确匹配,并且可以从左侧或右侧开始搜索。请参阅以下示例以了解其工作原理:

import numpy as np
a = np.array([10, 20, 30])

a.searchsorted(-99) == a.searchsorted(0) == a.searchsorted(10)
# returns index 0 for value 10

a.searchsorted(20.1) == a.searchsorted(29.9) == a.searchsorted(30)
# returns index 2 for value 30

a.searchsorted(30.1) == a.searchsorted(99) == a.searchsorted(np.nan)
# returns index 3 for undefined value

对于最后一种情况,返回索引为3,您可以根据需要处理。我从找到第一个合适索引后停止的函数的名称和意图中收集。