我想检查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
?
感谢您的帮助!
答案 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
对前两项0
和False
进行相等性测试,结果为In [51]: np.equal.reduce([False, 0, 1])
Out[51]: True
:
False
现在对0
和True
进行相等性测试,结果为In [52]: np.equal.reduce([True, 1])
Out[52]: True
:
True
但True
和1相等,因此总结果为reduce
,这不是理想的结果。
问题在于np.all
尝试“本地”累积结果,而我们想要{{1}}等“全局”测试。
答案 1 :(得分:7)
鉴于ubuntu的精彩解释,您可以使用reduce
来解决您的问题,但必须将其应用于bitwise_and
和bitwise_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/A和the bug I filed with numpy,提供的解决方案仅适用,因为您的数组包含零和1。碰巧,显示的bitwise_and.reduce()
操作只能返回零或一,因为bitwise_and.identity
是1
,而不是-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]])