42

我想检查 numpy 数组/矩阵的列中的所有值是否相同。我尝试使用reduceufunc equal但似乎并非在所有情况下都有效:

In [55]: a = np.array([[1,1,0],[1,-1,0],[1,0,0],[1,1,0]])

In [56]: a
Out[56]: 
array([[ 1,  1,  0],
       [ 1, -1,  0],
       [ 1,  0,  0],
       [ 1,  1,  0]])

In [57]: np.equal.reduce(a)
Out[57]: array([ True, False,  True], dtype=bool)

In [58]: a = np.array([[1,1,0],[1,0,0],[1,0,0],[1,1,0]])

In [59]: a
Out[59]: 
array([[1, 1, 0],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

In [60]: np.equal.reduce(a)
Out[60]: array([ True,  True,  True], dtype=bool)

为什么第二种情况下的中间列也评估为True,而应该是False

谢谢你的帮助!

4

3 回答 3

72
In [45]: a
Out[45]: 
array([[1, 1, 0],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

将每个值与第一行中的对应值进行比较:

In [46]: a == a[0,:]
Out[46]: 
array([[ True,  True,  True],
       [ True, False,  True],
       [ True, False,  True],
       [ True,  True,  True]], dtype=bool)

如果该列中的所有值都为 True,则该列共享一个公共值:

In [47]: np.all(a == a[0,:], axis = 0)
Out[47]: array([ True, False,  True], dtype=bool)

np.equal.reduce可以通过微观分析将其应用于 时发生的情况来看出问题[1, 0, 0, 1]

In [49]: np.equal.reduce([1, 0, 0, 1])
Out[50]: True

前两项,10进行相等性测试,结果为False

In [51]: np.equal.reduce([False, 0, 1])
Out[51]: True

现在False0进行相等性测试,结果是True

In [52]: np.equal.reduce([True, 1])
Out[52]: True

但是True和 1 相等,所以总结果是True,这不是期望的结果。

问题是reduce试图在“本地”累积结果,而我们想要一个像np.all.

于 2013-02-13T18:55:11.883 回答
9

鉴于 ubuntu 的精彩解释,您可以使用它reduce来解决您的问题,但您必须将其应用于bitwise_andandbitwise_or而不是equal. 因此,这不适用于浮点数组:

In [60]: np.bitwise_and.reduce(a) == a[0]
Out[60]: array([ True, False,  True], dtype=bool)

In [61]: np.bitwise_and.reduce(b) == b[0]
Out[61]: array([ True, False,  True], dtype=bool)

基本上,您正在比较列中每个元素的位。相同的位不变。不同的位设置为零。这样,任何具有零而不是一位的数字都会改变减少的值。bitwise_and不会捕获引入而不是删除位的情况:

In [62]: c = np.array([[1,0,0],[1,0,0],[1,0,0],[1,1,0]])

In [63]: c
Out[63]: 
array([[1, 0, 0],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

In [64]: np.bitwise_and.reduce(c) == c[0]
Out[64]: array([ True,  True,  True], dtype=bool)

第二个显然是错误的。我们需要用来bitwise_or捕获新的位:

In [66]: np.bitwise_or.reduce(c) == c[0]
Out[66]: array([ True, False,  True], dtype=bool)

最终答案

In [69]: np.logical_and(np.bitwise_or.reduce(a) == a[0], np.bitwise_and.reduce(a) == a[0])
Out[69]: array([ True, False,  True], dtype=bool)

In [70]: np.logical_and(np.bitwise_or.reduce(b) == b[0], np.bitwise_and.reduce(b) == b[0])
Out[70]: array([ True, False,  True], dtype=boo

In [71]: np.logical_and(np.bitwise_or.reduce(c) == c[0], np.bitwise_and.reduce(c) == c[0])
Out[71]: array([ True, False,  True], dtype=bool)

这种方法比 ubunut 建议的 using 更具限制性且不那么优雅all,但如果您的输入很大,它的优点是不会创建大量临时数组。临时数组应该只与矩阵的第一行一样大。

编辑

基于此Q/A我使用 numpy 提交的错误,提供的解决方案仅有效,因为您的数组包含零和一。碰巧的是,bitwise_and.reduce()显示的操作只能返回零或一,因为bitwise_and.identityis 1, not -1。我保留这个答案,希望numpy得到修复并且答案变得有效。

编辑

看起来实际上很快就会对 numpy 进行更改。当然 to bitwise_and.identity,也可能是一个可选参数来减少。

编辑

大家好消息。的标识np.bitwise_and已设置-1为 version 1.12.0

于 2016-01-19T14:51:07.010 回答
2

不那么优雅,但也可以在上面的示例中使用。

a = np.array([[1,1,0],[1,-1,0],[1,0,0],[1,1,0]])

取每一行与其上一行之间的差异

np.diff(a,axis=0)==0 

array([[ True, False,  True],
       [ True, False,  True],
       [ True, False,  True]])    
于 2020-05-31T21:49:53.663 回答