如何检测numpy数组中元素的符号更改

Rob*_*tie 25 python numpy

我有一个numpy数组,其中包含正值和负值.

a = array([1,1,-1,-2,-3,4,5])
Run Code Online (Sandbox Code Playgroud)

我想创建另一个数组,其中包含每个索引处发生符号更改的值(例如,如果当前元素为正,而前一个元素为负,反之亦然).

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

array([0,0,1,0,0,1,0])
Run Code Online (Sandbox Code Playgroud)

或者,发生符号变化的阵列中的位置列表或者布尔列表而不是0和1的列表是可以的.

jan*_*neb 25

就像是

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])
Run Code Online (Sandbox Code Playgroud)

现在,numpy.roll执行循环移位,因此如果最后一个元素的符号与第一个元素的符号不同,则signchange数组中的第一个元素将为1.如果不需要,那么当然可以做一个简单的

signchange[0] = 0
Run Code Online (Sandbox Code Playgroud)

此外,np.sign认为0具有自己的符号,不同于正值或负值.例如,[-1,0,1]的"signchange"数组将为[0,1,1],即使零线仅"交叉"一次.如果这是不希望的,可以插入线

sz = asign == 0
while sz.any():
    asign[sz] = np.roll(asign, 1)[sz]
    sz = asign == 0
Run Code Online (Sandbox Code Playgroud)

在第一个例子中第2行和第3行之间.

  • 请注意,如果最后一个元素与第一个元素的符号不同,则这将指示第一个位置的符号更改.它还认为0是一个不同于正面或负面的标志.所以`[-1,0,1]`会给`signchange = [1,1,1]`.这可能是期望的行为,但我想我会指出它. (2认同)

Chr*_*lis 17

(numpy.diff(numpy.sign(a)) != 0)*1
Run Code Online (Sandbox Code Playgroud)


Dou*_*ugR 8

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

import numpy as np
a = np.array([1,1,-1,-2,-3,4,5])
Run Code Online (Sandbox Code Playgroud)

方法一:数组中相邻项相乘,求负数

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)
Run Code Online (Sandbox Code Playgroud)

方法 2(最快):相邻符号不相等的地方

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)
Run Code Online (Sandbox Code Playgroud)

方法 3:由 ianalis 提出。大多数 IMO 优雅但有点慢

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)
Run Code Online (Sandbox Code Playgroud)

编辑:

对于大型数组,方法 1 是最好的。

在此处输入图片说明