NumPy - 连续三个连续负数的指数

时间:2018-06-14 09:05:51

标签: python arrays algorithm numpy

我需要找到第一次出现三个连续负数的索引。以普通的Python方式,我会这样做:

a = [1,-1,1,-1,1,-1,1,-1,-1,-1,1,-1,1]
b=0
for i,v in enumerate(a):
    if v<0:
        b+=1
    else:
        b=0
    if b==3:
        break
indx = i-2

任何人都知道如何以更聪明的NumPy方式做到这一点?

3 个答案:

答案 0 :(得分:3)

这是一个在卷积帮助下的矢量化解决方案 -

def first_consecutive_negative_island(a, N=3):
    mask = np.convolve(np.less(a,0),np.ones(N,dtype=int))>=N
    if mask.any():
        return mask.argmax() - N + 1
    else:
        return None

示例运行 -

In [168]: a = [1,-1,1,-1,1,-1,1,-1,-1,-1,1,-1,1]

In [169]: first_consecutive_negative_island(a, N=3)
Out[169]: 7

无论小组在哪里都有效 -

In [175]: a
Out[175]: [-1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1]

In [176]: first_consecutive_negative_island(a, N=3)
Out[176]: 0

没有负数,它会优雅地返回None -

In [183]: a
Out[183]: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

In [184]: first_consecutive_negative_island(a, N=3)

对于正好三个连续的负数搜索,我们可以使用切片,如此 -

def first_consecutive_negative_island_v2(a):
    m =  np.less(a,0)
    mask = m[:-2] & m[1:-1] & m[2:]
    if mask.any():
        return mask.argmax()
    else:
        return None

计时 -

In [270]: a = np.random.randint(-1,2,(1000000)).tolist()

In [271]: %timeit first_consecutive_negative_island(a, N=3)
10 loops, best of 3: 44.5 ms per loop

In [272]: %timeit first_consecutive_negative_island_v2(a)
10 loops, best of 3: 38.7 ms per loop

答案 1 :(得分:0)

import numpy as np
a = np.array([1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,1])
item_index = np.where(a < 0)
for a,b in zip( item_index[0],item_index[0][2:]):
    if b-a == 2: 
        break
index_ = a

答案 2 :(得分:0)

根本不需要循环。也没有拉链。只需执行以下操作:

a = np.array([1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1])
idx = np.where(a < 0)[0][:3]

np.where返回tuple,其中包含所选条件的索引。 [0]索引此元组的第一个维度(对于1D输入数组,这是唯一的维度),[:3]将这些索引切片为仅使用前三个索引。

如果需要出现前三个连续负数,您可以执行以下操作:

idx = np.where(np.diff(np.where(a < 0), n=2) == 0)[1][0] + 2

这将为您提供三个连续负数的第一个负数的索引。如果您想要所有三个第一个负连续数字的索引,请执行以下操作:

idx_start = np.where(np.diff(np.where(a < 0), n=2) == 0)[1][0] + 2
idx = np.arange(idx_start, idx_start + 3)

只要数组中的前两个数字不是三个连续负数的一部分,这将有效。