我有一个numpy数组,其中有正值和负值。
a = array([1,1,-1,-2,-3,4,5])
我想创建另一个数组,其中包含每个索引处发生符号更改的值(例如,如果当前元素为正且前一个元素为负数,反之亦然)。
对于上面的数组,我希望得到以下结果
array([0,0,1,0,0,1,0])
或者,数组中符号发生变化的位置列表或布尔值列表而不是0和1是很好。
答案 0 :(得分:24)
像
这样的东西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执行循环移位,因此如果最后一个元素的符号与第一个元素的符号不同,则signchange数组中的第一个元素将为1.如果不希望这样,那么当然可以做一个简单的< / p>
signchange[0] = 0
此外,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
第一个例子中第2行和第3行之间的。
答案 1 :(得分:17)
(numpy.diff(numpy.sign(a)) != 0)*1
答案 2 :(得分:2)
import numpy as np
a = np.array([1,1,-1,-2,-3,4,5])
方法1:将数组中的相邻项相乘并找到负数
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)
方法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)
方法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)
答案 3 :(得分:1)
怎么样
[0 if x == 0 else 1 if numpy.sign(a[x-1]) != numpy.sign(y) else 0 for x, y in enumerate(a)]
numpy.sign指定0自己的符号,所以0将是除了其他0之外的任何符号的符号更改,这可能是你想要的。
答案 4 :(得分:1)
上面的答案使用列表推导和一些numpy魔法来获得你想要的结果。这是一个非常直接的,如果有点复杂,做同样的方式:
import numpy as np
arr = np.array([1,1,-1,-2,-3,4,5])
result = []
for i, v in enumerate(arr):
if i == 0:
change = False
elif v < 0 and arr[i-1] > 0:
change = True
elif v > 0 and arr[i-1] < 0:
change = True
else:
change = False
result.append(change)
print result
答案 5 :(得分:0)
对于这个问题的直接解释,0不是他们自己的情况,使用greater
比使用sign
更容易。这是一个例子:
a = array([1, 1, -1, -2, -3, 0, 4, 0, 5, 6])
x = greater_equal(a, 0)
sign_change = x[:-1]-x[1:]
使用T
或F
打印时,表示不同数字之间的符号更改:
1 F 1 T -1 F -2 F -3 T 0 F 4 F 0 F 5 F 6
使用时打印:
print `a[0]`+"".join([(" T" if sign_change[i] else " F")+" "+`a[i+1]` for i in range(len(sign_change))])
另请注意,这是一个比原始数组短的元素,这是有道理的,因为您要求更改符号。如果要在最后一个元素和第一个元素之间包含更改,可以像其他人所建议的那样使用roll
。
答案 6 :(得分:0)
让“严格”符号从正变为负和从负变为正(不包括零)的另一个想法:
a = np.array([0.4, 0.5, -0.2, -0.6, 5, 0, 0, 5, 0,-2])
# Get associated index
ind =np.arange(len(a))
# remove zero from array but keep original index
a2 =a[a!=0.]
ind2 =ind[a!=0.]
# Detect sign changes in reduced array
idx=np.where(np.diff(np.sign(a2)) != 0)[0] + 1
# Get sign changes index for original array
ind2[idx]
array([2, 4, 9])