【问题标题】:Get groups of consecutive elements of a NumPy array based on multiple conditions根据多个条件获取 NumPy 数组的连续元素组
【发布时间】:2019-07-09 20:26:25
【问题描述】:

我有 2 个 NumPy 数组如下:

import numpy as np
a = np.array([1, 4, 2, 6, 4, 4, 6, 2, 7, 6, 2, 8, 9, 3, 6, 3, 4, 4, 5, 8])
b = np.array([2, 8, 3, 9, 9, 9, 7, 5, 4, 8, 6, 5, 4, 4, 7, 2, 1, 1, 9, 9])

和2个常数:

c = 6
d = 3

基于a previous question,每次a中的元素小于c,我可以提取一个数组,连续2次或更多次:

array = np.append(a, -np.inf)  # padding so we don't lose last element
mask = array >= c  # values to be removed
split_indices = np.where(mask)[0]
for subarray in np.split(array, split_indices + 1):
    if len(subarray) > 2:
        print(subarray[:-1])

哪个输出:

[1. 4. 2.]
[4. 4.]
[3. 4. 4. 5.]

现在,我想将我的条件更改为多个条件,其中连续 2 次或更多次:

  1. a 中的元素小于c

  1. b 中的元素小于d

使用以下代码:

mask = ((a< c) & (b< d))

我知道我的条件(连续 2 次或更多次)在索引 151617 处仅满足 1 次。

现在我想提取与我的条件满足的那些索引对应的a 的值。

根据链接答案,我尝试了:

a1= np.append(a, -np.inf)
a2=np.append(b, -np.inf)  # padding so we don't lose last element
mask = ((a1< c) & (a2< d))  # values to be removed
split_indices = np.where(mask)[0]
for subarray in np.split(a, split_indices + 1):
    if len(subarray) > 2:
        print(subarray[:-1])

令人惊讶的是,返回一个我的条件不符合的数组...

[4 2 6 4 4 6 2 7 6 2 8 9 3 6]

我也试过np.extract如下:

np.extract((len(list(g))>=2 for i, g in ((a < c) & (b < d)) if i), a)

返回的值是1,而不是数组的值a...

所需的输出数组应该是索引151617 之一,对应于数组[3 4 4] 中的值[3 4 4]

有人可以指出我可以使用哪些 python 工具来提取满足我的多个条件的数组吗?

注意:这是我的问题的一个最小示例,在我的“现实生活”中,我需要找到连续 14 次或更多次满足我的条件的数组!

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    请注意,在您的 previous question 中,当您在 array 中查找小于 threshold 的元素时,您的 mask 不是定义为 mask = array &lt; threshold,而是定义为它的倒数:mask = array &gt;= threshold .这是因为它后来被用来获取将被删除的元素。

    因此,在您的新示例中,您还必须得到掩码的倒数。你需要mask = ~((a1 &lt; c) &amp; (a2 &lt; d)),而不是mask = (a1 &lt; c) &amp; (a2 &lt; d)

    a1= np.append(a, -np.inf)
    a2 = np.append(b, -np.inf)
    mask = ~((a1 < c) & (a2 < d))
    split_indices = np.where(mask)[0]
    for subarray in np.split(a, split_indices + 1):
        if len(subarray) > 2:
            print(subarray[:-1])
    

    给予:

    [3 4 4]
    

    这是a的第15-17个元素。

    【讨论】:

      【解决方案2】:

      按照条件,放置两个条件后您想要的输出是:[3,4,4] from a[2,1,1] from b 对吗?

      试试:

      a = [1, 4, 2, 6, 4, 4, 6, 2, 7, 6, 2, 8, 9, 3, 6, 3, 4, 4, 5, 8]
      b = [2, 8, 3, 9, 9, 9, 7, 5, 4, 8, 6, 5, 4, 4, 7, 2, 1, 1, 9, 9]
      c = 6
      d = 3
      condition_met = []
      a_extract = []
      b_extract = []
      
      for i in range(0, len(a)):
          if a[i] < c and b[i] < d:
              condition_met.append(True)
          else:
              condition_met.append(False)
      

      打印condition_met 列表给出[True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, False, False]

      使用它,我们现在检查您的条件:

      for i in range(0, len(condition_met)):
          if i == 0 and condition_met[i] == True and condition_met[i+1] == True:
              a_extract.append(a[i])
              b_extract.append(b[i])
          elif condition_met[i] == True and condition_met[i+1] == True and i != len(condition_met) - 1 and i > 0 or condition_met[i] == True and condition_met[i-1] == True and i != len(condition_met) - 1 and i > 0:
              a_extract.append(a[i])
              b_extract.append(b[i])
          elif condition_met[i] == True and condition_met[i-1] == True and i == len(condition_met) - 1:
              a_extract.append(a[i])
              b_extract.append(b[i])
      

      您的a_extract 列表将获得[3,4,4]b_extract 列表将获得[2,1,1]

      这是你需要的吗?

      【讨论】:

      • a_extract 列表是您正在寻找的列表,我刚刚添加了 b_extract 以显示多功能性:))。如果这对您有帮助,请告诉我。
      • 它确实有效!谢谢你。但是你能解释一下2 times or more consecutively条件在哪里以及如何满足,在这段代码中应用吗?因为这是我需要做的任务的一个最小示例,在我的现实生活问题中,条件需要连续满足 14 次或更多次...... :)
      • 我明白了,我确实使用您的条件 (a &lt; c and b &lt; d) 用布尔值 (True or False) 填充 codition_met 列表。现在确定要获取哪个列表元素是那些TrueFalse 值的定位,对吗?基本上,两个直的True 将满足您的条件,如果您在第二个for 循环中的i 大于0 或小于len(condition_met) - 1,那么直的True 位于左侧或右侧。如果i 等于0,请检查列表中的0th 位置和i+1th 位置。如果i 等于len - 1,则检查i-1th 位置
      【解决方案3】:

      您可以使用 SciKit 图像创建蒙版,例如

      import numpy as np
      import skimage
      
      N = 2
      mask = ((a < c) & (b < d))
      mask2 = np.zeros_like(mask)
      
      tmp = skimage.util.view_as_windows(mask, N).all(axis=1)
      mask2[N - 1:-N + 1] = skimage.util.view_as_windows(tmp, N).any(axis=1)
      mask2
      # array([False, False, False, False, False, False, False, False, False,
      #        False, False, False, False, False, False,  True,  True,  True,
      #        False, False])
      

      并使用获取索引和值

      np.where(mask2)[0]  # array([15, 16, 17])
      a[mask2]  # array([3, 4, 4])
      

      【讨论】:

      • 感谢您的回答。我真的不明白这段代码中实现的“连续两次或更多次”在哪里。我的问题需要让这段代码连续工作 14 次或更多次。
      • view_as_windows() 在数组上创建一个重叠视图,在这种情况下,每行有 2 个连续值。在该轴上执行.all(),您将知道条件对于 2 个连续值是否为真。
      • 谢谢!但是我不能连续修改此代码 14 次或更多次?
      • 是的,只需将 2 改为 14 即可?
      • 当我将 2 更改为任何其他值时,它不起作用。假设我将数组ab 修改为:a = np.array([1, 4, 2, 6, 4, 4, 6, 2, 7, 6, 2, 8, 9, 3, 2, 3, 4, 4, 5, 8]) b = np.array([2, 8, 3, 9, 9, 9, 7, 5, 4, 8, 6, 5, 4, 4, 2, 2, 1, 1, 9, 9]) 我现在正在搜索条件是否连续满足 4 次或更多次,方法是将 2 更改为 4。它总是返回我ValueError: could not broadcast input array from shape (14) into shape (18)
      猜你喜欢
      • 1970-01-01
      • 2019-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-21
      • 1970-01-01
      • 2020-06-06
      相关资源
      最近更新 更多