我有一个包含正数和负数的numpy数组。
a = array([1,1,-1,-2,-3,4,5])
我想创建另一个数组,其中包含在发生符号更改的每个索引处的值(例如,如果当前元素为正数且上一个元素为负数,反之亦然)。
对于上面的数组,我期望得到以下结果
array([0,0,1,0,0,1,0])
或者,将数组中符号变化发生的位置的列表或布尔值列表作为0和1的替代,都可以。
类似以下内容
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。如果不希望这样,当然可以进行简单的操作
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行之间。
(numpy.diff(numpy.sign(a)) != 0)*1
diff
和 sum
的轴。 - Christian Alis*1
是什么作用? - undefinedTrue
转换为1
,将False
转换为0
。 - undefinedimport 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)
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)
对于大型数组,方法1是最佳选择。
关于将“严格”符号从正变为负、从负变为正(不包括零)的另一个想法:
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])
怎么样?
[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之外的任何数的符号变化,这可能是您想要的。
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
np.array([1,0,-1])
中注册更改。 - Justin Peel对于这个问题的直接解释,其中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
,正如其他人建议的那样。
-
operator, is deprecated, use the bitwise_xor, the ^
operator, or the logical_xor function instead. 请使用其他解决方案。 - shantanu pathaknp.where(np.diff((arr>=0)*1)==1)
返回符号改变前每个最后一个负值的索引
[-1, 0, 1]
将给出signchange = [1, 1, 1]
。这可能是期望的行为,但我想指出这一点。 - tgray