有没有一种Python的有效方法来检查Numpy数组是否包含给定行的至少一个示例?所谓“高效”,我的意思是它在找到第一个匹配行时终止,而不是迭代整个数组,即使已经找到了结果。
对于Python数组,这可以用if row in array:
非常干净地完成,但这并不像我期望的Numpy数组那样工作,如下所示。
Python数组:
>>> a = [[1,2],[10,20],[100,200]]
>>> [1,2] in a
True
>>> [1,20] in a
False
但是Numpy数组给予了不同的、看起来相当奇怪的结果。(ndarray
的__contains__
方法似乎没有文档记录。
>>> a = np.array([[1,2],[10,20],[100,200]])
>>> np.array([1,2]) in a
True
>>> np.array([1,20]) in a
True
>>> np.array([1,42]) in a
True
>>> np.array([42,1]) in a
False
6条答案
按热度按时间w3nuxt5m1#
可以使用.tolist()
或者使用视图:
或者在numpy列表上生成(可能非常慢):
或者使用numpy逻辑函数:
如果您对这些时间进行计时:
你可以看到,无论命中或未命中,numpy例程都以相同的速度搜索数组。Python
in
运算符对于早期命中来说 * 可能 * 要快得多,如果你必须一路遍历数组,那么生成器就是个坏消息。以下是300,000 x 3元素数组的结果:
对于3,000,000 x 3阵列:
这似乎表明
np.equal
是最快的纯numpy方式来做到这一点。wkyowqbh2#
在写这篇文章的时候,Numpys
__contains__
是(a == b).any()
,可以说只有当b
是标量时才是正确的(这有点麻烦,但我相信-只有在1.7中才能这样工作。或以后-这将是正确的通用方法(a == b).all(np.arange(a.ndim - b.ndim, a.ndim)).any()
,这对a
和b
维度的所有组合都有意义)...编辑:只是要明确,这是 * 不 * 一定是预期的结果时,广播参与。另外,有人可能会争辩说,它应该像
np.in1d
那样单独处理a
中的项。我不确定是否有一种明确的方法可以奏效。现在,您希望numpy在找到第一个匹配项时停止。此AFAIK此时不存在。这很困难,因为numpy主要基于ufuncs,它对整个数组做同样的事情。Numpy确实优化了这类缩减,但实际上只有当被缩减的数组已经是布尔数组时才有效(即
np.ones(10, dtype=bool).any()
)。否则,它将需要一个不存在的
__contains__
的特殊函数。这可能看起来很奇怪,但你必须记住,numpy支持许多数据类型,并且有一个更大的机制来选择正确的数据类型并选择正确的函数来处理它。所以换句话说,ufunc机器不能做到这一点,并且由于数据类型的原因,实现__contains__
或类似的特殊功能实际上并不是那么简单。你当然可以用python来写,或者因为你可能知道你的数据类型,所以用Cython/C自己写非常简单。
也就是说,通常使用基于排序的方法来处理这些事情要好得多。这有点乏味,而且对于
lexsort
没有searchsorted
这样的东西,但它可以工作(如果你喜欢,你也可以滥用scipy.spatial.cKDTree
)。这假设您只想沿着最后一个轴进行比较:这也适用于数组
b
,如果你保持有序数组,如果你一次对b
中的单个值(行)执行,当a
保持不变时(否则我将在将其视为recarray后仅为np.in1d
)。* 重要提示:* 为了安全,您必须执行np.ascontiguousarray
。它通常不会做任何事情,但如果它做了,这将是一个很大的潜在错误。suzh9iv83#
我觉得
将列出匹配的行。正如Jamie指出的,要知道是否至少存在一个这样的行,使用
any
:旁白:
我怀疑
in
(和__contains__
)和上面一样,但是使用any
而不是all
。gtlvzcf84#
我将建议的解决方案与perfplot进行了比较,发现如果您在一个长的未排序列表中查找一个2元组,
是最快的解决方案。如果在前几行中找到匹配,则显式短路循环总是更快。
用于重现绘图的代码:
ukdjmx9f5#
如果你真的想在第一次出现时停止,你可以写一个循环,比如:
然而,我强烈怀疑,它会比其他使用numpy例程对整个数组执行的建议慢得多。
qybjjes16#
要知道一个特定的一维numpy数组(行)是否存在于二维numpy数组中,一种更简单的方法是使用以下条件。
如果
np.sum(np.prod(2-darray == 1-darray),axis = 1))
大于0
,则该行存在于2-D阵列中,否则不存在。