如何检测numpy数组中元素的符号变化

36 投票
8 回答
41526 浏览
提问于 2025-04-15 21:41

我有一个包含正数和负数的numpy数组。

a = array([1,1,-1,-2,-3,4,5])

我想创建另一个数组,这个数组在每个索引位置上记录符号变化的值(比如,如果当前元素是正数,而前一个元素是负数,或者反过来)。

对于上面的数组,我希望得到以下结果

array([0,0,1,0,0,1,0])

另外,给出数组中符号变化发生的位置列表,或者用布尔值代替0和1也是可以的。

8 个回答

14

三种方法来确定符号变化的位置

import numpy as np
a = np.array([1,1,-1,-2,-3,4,5])

方法一:把数组中相邻的元素相乘,找出负数

idx1 = np.where(a[:-1] * a[1:] < 0 )[0] +1
idx1
Out[2]: array([2, 5], dtype=int64)

%timeit np.where(a[:-1] * a[1:] < 0 )[0] + 1
4.31 µs ± 15.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

方法二(最快):检查相邻的符号是否不相等

idx2 = np.where(np.sign(a[:-1]) != np.sign(a[1:]))[0] + 1
idx2
Out[4]: array([2, 5], dtype=int64)

%timeit np.where(np.sign(a[:-1]) != np.sign(a[1:]))[0] + 1
3.94 µs ± 20.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

方法三:由ianalis提出。最优雅,但稍微慢一点

idx3 = np.where(np.diff(np.sign(a)) != 0)[0] + 1
idx3
Out[6]: array([2, 5], dtype=int64)

%timeit np.where(np.diff(np.sign(a)) != 0)[0] + 1
9.7 µs ± 36.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

编辑:

对于大数组,方法一是最好的选择。

在这里输入图片描述

27

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。比如说,当你在写代码时,可能会发现某个功能没有按预期工作。这时候,很多人会去网上查找解决方案,比如在StackOverflow上提问或者寻找答案。

StackOverflow是一个程序员交流的平台,大家可以在这里分享自己的问题和解决方案。当你在这个平台上提问时,其他程序员会看到你的问题,并尝试给你提供帮助。他们可能会建议你检查代码的某个部分,或者提供一些代码示例来帮助你理解。

总之,StackOverflow是一个很好的资源,可以帮助你解决编程中遇到的各种问题。只要你描述清楚你的问题,通常都会有人愿意帮你。

(numpy.diff(numpy.sign(a)) != 0)*1
37

类似这样的内容

a = array([1,1,-1,-2,-3,4,5])
asign = np.sign(a)
signchange = ((np.roll(asign, 1) - asign) != 0).astype(int)
print signchange
array([0, 0, 1, 0, 0, 1, 0])

现在,numpy.roll 这个函数会进行循环移动,所以如果最后一个元素的符号和第一个元素不同,那么在符号变化的数组里,第一个元素会是 1。如果你不想要这个效果,可以简单地使用

signchange[0] = 0

另外,np.sign 这个函数认为 0 有它自己的符号,这个符号和正数或负数都不一样。比如,对于数组 [-1,0,1],符号变化的数组会是 [0,1,1],尽管零只“跨越”了一次。如果你不想要这个效果,可以在第一个例子的第 2 行和第 3 行之间插入以下代码

sz = asign == 0
while sz.any():
    asign[sz] = np.roll(asign, 1)[sz]
    sz = asign == 0

撰写回答