Python 与list.index等价的Numpy
在一个被多次调用的低级函数中,我需要执行与python的list.index等效的操作,但要使用numpy数组。函数需要在找到第一个值时返回,否则将引发ValueError。比如:Python 与list.index等价的Numpy,python,numpy,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>",
>>> 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
>a=np.array([1,2,3])
>>>np_指数(a,1)
0
>>>np_指数(a,10)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
ValueError:10不在数组中
我希望尽可能避免Python循环np。其中
不是一个选项,因为它总是遍历整个数组;我需要一个一旦找到第一个索引就停止的东西
编辑:一些与问题相关的更具体信息
- 大约90%的时候,我搜索的索引位于数组的前1/4到1/2。所以这里有一个潜在的2-4加速因子。其他10%的时间该值根本不在数组中
- 我已经分析过了,对
至少占据了总运行时间的50%np的调用是瓶颈,
- 它不一定会引发
;它只需要返回一些明显指示该值不在数组中的内容值错误
我可能会按照建议用Cython编写一个解决方案。我能找到的最接近您要求的东西是非零。这听起来可能有点奇怪,但文档让它看起来可能达到了预期的效果 具体而言,本部分: a、 非零() 返回非零元素的索引 有关完整文档,请参阅
numpy.nonzero
另见
numpy.nonzero:等价函数
在哪里(http://www.scipy.org/Numpy_Example_List_With_Doc#where)您可能也感兴趣。有关注意事项,请参阅我对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循环搜索整个数组时,它的速度相对较快。在发现第一个值时坚持停止搜索可能在功能上不相关 NumPy的索引与list的索引非常相似,不同之处在于它需要一个排序数组,并且其行为更符合数字。最大的区别在于不需要精确匹配,可以从左侧或右侧开始搜索。请参见以下示例了解其工作原理:
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,您可以随意处理。我从函数的名称和意图推断,在找到第一个合适的索引后,函数将停止。您可以用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
我唯一一次遇到这个问题时,将numpy数组强制转换为列表就足够了:
a = numpy.arange(3)
print(list(a).index(2))
>>> 2
如果您的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
那么你有一个numpy数组还是什么?是的;我对问题进行了编辑以澄清问题。您是否对代码进行了分析,以便您真正知道
哪里是瓶颈。您可以显示代码的该部分。您要查找的AFAIK功能在numpy
中不存在。谢谢,我同意@eat。我认为numpy中没有一种方法可以满足您的要求,尤其是返回ValueError
。如果您想避免python循环,我建议您应该在cython
中编写自己的函数,这应该是快速的,并且完全按照您的要求执行。我也同意你应该分析你的代码,使用nonzero
或where
然后找到min
索引实际上是你代码中的瓶颈。相反,如果您多次调用该函数,那么问题应该是您是否可以在单个数组操作可能工作时使用numpy来避免多次调用。在numpy
中的where
和matlab中的find
中,我从未遇到过任何严重的性能问题。(虽然有时简单的逻辑索引
就足以胜任这项工作)我不会期望从cython
中得到任何重大改进,除非你能想出一个非常具体的解决方案(视情况而定)。但是,您是否愿意向我们展示您当前的瓶颈代码?谢谢,但是y>=5
和nonzero(y)
命中了每个数组元素——我正在寻找一个函数,它在找到第一个索引后立即返回。这是正确的,如果你使用np.nonzero(y==index\u值)[0][0]
它似乎在复制一个numpy数组的y.index(index\u值)
,虽然我还没有对它进行广泛的测试,但我不知道它是否可以这样使用。它依赖于二进制搜索,OP没有指定他的数组已经排序。list.index依赖于排序数组,文档中的“二进制搜索”部分只是对那些混合数据类型(即,a=np.array([2.1,3.1,4.1],dtype=np.float16);a.searchsorted(np.float32(3.1))的警告
返回2,而不是预期的1)list.index不依赖排序数组。哦,对了,list.index返回第一个索引(如果有)。是的,此解决方案仅适用于排序数组。
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