在numpy中检查两个数值是否具有相同的符号(+/-)。

7

目前,我正在使用numpy.logical_or和numpy.logical_and来检查两个数组的元素是否具有相同的符号。想知道是否已经有ufunc或更有效的方法可以实现这一点。我的当前解决方案在这里。

a = np.array([1,-2,5,7,-11,9])
b = np.array([3,-8,4,81,5,16])
out = np.logical_or(
                    np.logical_and((a < 0),(b < 0)), 
                    np.logical_and((a > 0),(b > 0))
                                             )

编辑//输出

out
Out[51]: array([ True,  True,  True,  True, False,  True], dtype=bool)

零怎么办?零和零有相同的符号,但你没有意识到它。 - Stefan Pochmann
不要忘记浮点数有一个带符号的零。 - wim
是的!从这里的答案中我意识到在使用零时必须小心。无论如何,我的当前解决方案并不有效,因此提出了问题。谢谢,SO太棒了。 - Siraj S.
6个回答

21

通过对每个元素进行逐个相乘,并检查是否>=0,这种方法会产生正数结果,因为符号相同(两个数都是正数或者两个数都是负数)的元素相乘会得到正数值 -

((a== b) & (a==0)) | (a*b>0)

带有显式符号检查的另一个示例 -

np.sign(a) == np.sign(b)

运行时测试 -

In [155]: a = np.random.randint(-10,10,(1000000))

In [156]: b = np.random.randint(-10,10,(1000000))

In [157]: np.allclose(np.sign(a) == np.sign(b), ((a== b) & (a==0)) | (a*b>0))
Out[157]: True

In [158]: %timeit np.sign(a) == np.sign(b)
100 loops, best of 3: 3.06 ms per loop

In [159]: %timeit ((a== b) & (a==0)) | (a*b>0)
100 loops, best of 3: 3.54 ms per loop

# @salehinejad's soln
In [160]: %timeit np.where((np.sign(a)+np.sign(b))==0)
100 loops, best of 3: 8.71 ms per loop

例如在a,b = np.array([0]),np.array([-1])的情况下,a * b> = 0无法满足。 - Stefan Pochmann
我也遇到了类似的矛盾情况。数学家永远不会声称 0 是正数。尽管如此,我认为 a*b>0 的条件是完全可以接受的。 - kmario23

4
在纯Python中,您可以执行以下操作:
abs(a + b) == abs(a) + abs(b)

如果符号相等,则返回true。

太复杂了。a * b > 0 更简单。 - Nico Schlömer

1
你可以依靠按位运算符XOR
x ^ y
XOR操作也应用于符号,因此当它们相同时,结果大于0,如果不同则小于0。

1

我不明白为什么没有人使用实际的数学运算:

a * b < 0

如果您需要不用numpy数组的公式


它应该大于0才能检查是否具有相同的符号。被接受的答案已经使用了这个方法,它也可以捕获当ab都为零的情况:((a==b) & (a==0)) | (a*b>0) - tdy

1

加法比乘法更便宜。对于不相等的符号:

np.where((np.sign(a)+np.sign(b))!=0)

对于等号:

np.where((np.sign(a)+np.sign(b))==0)

这种方法返回索引,不仅是True/False等。
给定问题中a和b的输出:
[0 1 2 3 5]
可以尝试np.sum()用于两个以上的变量。

哦,我很确定这只告诉你符号是否相反且相等,对吧? - juanpa.arrivillaga
np.sign() 返回 -1 或 +1。因此它忽略数值本身。 - salehinejad

1
import numpy as np
a = np.random.randn(5)
b = np.random.randn(5)

print a
print b

# Method 1
print np.logical_not(np.sign(a*b)-1)

# Method 2 ***probably best
print np.equal(np.sign(a), np.sign(b))

# Method 3
print np.where((a*b<0),np.zeros(5,dtype=bool),np.ones(5,dtype=bool))

# Method 4
print np.core.defchararray.startswith(np.array(-a*b).astype('str'),'-')

>>>
[-0.77184408 -0.55291345 -0.45774947  0.67080435 -0.286555  ]
[ 0.37220055  0.29489477 -1.05773195  1.03833121  1.01538001]
[False False True True False]
[False False True True False]
[False False True True False]
[False False True True False]

方法一

  • a*b生成一个值的数组,当符号不同时为负数
  • np.sign()将数组转换为-1和1
  • 减去1将数组转换为-2和0
  • np.logical_not()将-2转换为False;将0转换为True

方法二

  • np.sign()转换为-1, 1
  • np.equal()比较两个数组并按元素给出真值

方法三

  • np.where(condition[, x, y])根据条件返回元素,来自x或y。
  • np.zeros(5,dtype=bool),np.ones(5,dtype=bool)分别是False和True的数组

方法四

  • 相乘-a*b
  • 将结果数组转换为dtype字符串
  • 检查哪些元素以-开头

参考资料:

https://docs.scipy.org/doc/numpy/reference/generated/numpy.sign.html

https://docs.scipy.org/doc/numpy/reference/routines.logic.html

https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html

https://docs.scipy.org/doc/numpy/reference/generated/numpy.core.defchararray.startswith.html#numpy.core.defchararray.startswith


给np.equal的解决方案点赞,它是最直观的一步解决方案(与其他地方的加法、乘法等相比)。但@Divakar首先强调了它,所以将接受他的解决方案。 - Siraj S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接