Pythonic测试行是否在数组中的方法

时间:2011-07-03 05:14:02

标签: arrays testing numpy python

这似乎是一个简单的问题,但我找不到一个好的答案。

我正在寻找一种pythonic方法来测试2d numpy数组是否包含给定行。例如:

myarray = numpy.array([[0,1],
                       [2,3],
                       [4,5]])

myrow1 = numpy.array([2,3])
myrow2 = numpy.array([2,5])
myrow3 = numpy.array([0,3])
myrow4 = numpy.array([6,7])

鉴于myarray,我想编写一个函数,如果我测试myrow1则返回True,如果我测试myrow2,myrow3和myrow4则返回False。

我尝试了“in”关键字,并没有给出我预期的结果:

>>> myrow1 in myarray
True
>>> myrow2 in myarray
True
>>> myrow3 in myarray
True
>>> myrow4 in myarray
False

似乎只检查一个或多个元素是否相同,而不是所有元素都相同。有人可以解释为什么会这样吗?

我可以逐个元素地执行此测试,如下所示:

def test_for_row(array,row):
    numpy.any(numpy.logical_and(array[:,0]==row[0],array[:,1]==row[1]))

但是这不是非常pythonic,如果行有很多元素会变得有问题。必须有一个更优雅的解决方案。任何帮助表示赞赏!

5 个答案:

答案 0 :(得分:5)

下面的SO问题可以帮助你,但基本上你可以使用:

any((myrow1 == x).all() for x in myarray)

Numpy.Array in Python list?

答案 1 :(得分:3)

您只需从数组中减去测试行即可。然后找出零元素,并按列顺序求和。那些是匹配,其中总和等于列数。

例如:

In []: A= arange(12).reshape(4, 3)
In []: A
Out[]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
In []: 3== (0== (A- [3, 4, 5])).sum(1)
Out[]: array([False,  True, False, False], dtype=bool)

更新:根据评论和其他答案:
Paul的建议似乎确实能够简化代码:

In []: ~np.all(A- [3, 4, 5], 1)
Out[]: array([False,  True, False, False], dtype=bool)

JoshAdel的答案更普遍地强调与确定100%可靠的方式相关的问题。所以,显然我的答案只有在可以明确确定平等的情况下才有效。

更新2 :但是当Emma弄明白时,存在Paul解决方案无法产生正确结果的极端情况。

答案 2 :(得分:1)

这是@maz解决方案的概括,它更优雅地处理浮点数,严格的相等性将失败:

import numpy as np

def test_for_row(myarray,row):
    return any(np.allclose(row,x) for x in myarray)

有关详细信息,请参阅http://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html。另外作为旁注,请注意你没有像from numpy import *那样做np.any,而python的内置any会产生不同的答案,前者是不正确的。

答案 3 :(得分:0)

我遇到了同样的问题,以下方法对我有用

def is_row_in_matrix(row, matrix):
    return sum(np.prod(matrix == row, axis = 1))

基本上,测试行的每个元素是否在矩阵的相应列中,然后乘以列(axis = 1),并对结果求和。

答案 4 :(得分:0)

怎么样:

def row_in_array(myarray, myrow):
    return (myarray == myrow).all(-1).any()

这是您的测试用例的样子:

myarray = numpy.array([[0,1],
                       [2,3],
                       [4,5]])

row_in_array(myarray, [2, 3])
# True
row_in_array(myarray, [2, 5])
# False
row_in_array(myarray, [0, 3])
# False
row_in_array(myarray, [6, 7])
# False