【问题标题】:NumPy - catching the index of first three consecutive negative numbersNumPy - 捕获前三个连续负数的索引
【发布时间】:2018-11-24 00:10:32
【问题描述】:

我需要找到第一次出现三个连续负数的索引。在正常的 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 方式进行操作吗?

【问题讨论】:

  • 您可以尝试查看此链接。好像能帮到你。 Searching a sequence in a numpy array
  • 第一次出现三个连续负数的索引 - 所以你希望它是7?或[7,8,9] ?
  • 发布的解决方案是否对您有用?
  • 是的,first_consecutive_negative_island 正在做我必须做的事情......谢谢
  • @RomanPerekhrest 我希望它是7

标签: python arrays algorithm numpy


【解决方案1】:

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

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

【讨论】:

  • 你也可以卷积np.signbit(a)而不是np.less(a,0)以获得更快的速度(也许)。
【解决方案2】:

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

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] 索引此元组的第一个维度(对于一维输入数组,这是唯一的维度),[: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)

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

【讨论】:

    【解决方案3】:
    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
    

    【讨论】:

    • 这不是numpy 风格的答案。它使用zip AND 一个 for 循环。这既不是 Python 风格,也不是高效的 numpy 风格。
    猜你喜欢
    • 2021-08-12
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 2021-11-11
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多