如何检查numpy矩阵列中的所有值是否相同?

时间:2013-02-13 17:33:04

标签: python matrix numpy

我想检查numpy数组/矩阵的列中的所有值是否相同。 我尝试使用ufunc reduce的{​​{1}},但它似乎并不适用于所有情况:

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

感谢您的帮助!

3 个答案:

答案 0 :(得分:40)

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 的问题:

1

对前两项0False进行相等性测试,结果为In [51]: np.equal.reduce([False, 0, 1]) Out[51]: True

False

现在对0True进行相等性测试,结果为In [52]: np.equal.reduce([True, 1]) Out[52]: True

True

True和1相等,因此总结果为reduce,这不是理想的结果。

问题在于np.all尝试“本地”累积结果,而我们想要{{1}}等“全局”测试。

答案 1 :(得分:7)

鉴于ubuntu的精彩解释,您可以使用reduce来解决您的问题,但必须将其应用于bitwise_andbitwise_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使用all的建议更具限制性和优雅性,但它的优点是如果你的输入很大,就不会创建巨大的临时数组。临时数组应该只与矩阵的第一行一样大。

修改

根据此Q/Athe bug I filed with numpy,提供的解决方案仅适用,因为您的数组包含零和1。碰巧,显示的bitwise_and.reduce()操作只能返回零或一,因为bitwise_and.identity1,而不是-1。我保留这个答案,希望numpy得到修复,答案才有效。

修改

看起来事实上很快就会变成numpy。当然是bitwise_and.identity,也可能是减少的可选参数。

修改

大家好消息。自版本np.bitwise_and起,-1的身份已设置为1.12.0

答案 2 :(得分:1)

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

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]])