使用 NumPy 查找条件为 True 的范围

问题描述 投票:0回答:3
想象我有一个 numpy 数组,我需要找到该条件为 True 的跨度/范围。例如,我有以下数组,我试图在其中查找项目大于 1 的跨度:

[0, 0, 0, 2, 2, 0, 2, 2, 2, 0]

我需要找到索引(开始,停止):

(3, 5) (6, 9)

我能够实现的最快的事情是创建一个布尔数组:

truth = data > threshold

然后使用

numpy.argmin

numpy.argmax
 循环遍历数组以查找开始和结束位置。 

pos = 0 truth = container[RATIO,:] > threshold while pos < len(truth): start = numpy.argmax(truth[pos:]) + pos + offset end = numpy.argmin(truth[start:]) + start + offset if not truth[start]:#nothing more break if start == end:#goes to the end end = len(truth) pos = end

但是对于我的数组中的数十亿个位置来说这太慢了,而且我找到的跨度通常只是连续的几个位置。有谁知道找到这些跨度的更快方法?

python arrays search numpy
3个回答
7
投票
一种方法怎么样。首先获取您拥有的布尔数组:

In [11]: a Out[11]: array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0]) In [12]: a1 = a > 1

使用

roll

: 将其向左移动一位(以获取每个索引处的下一个状态)

In [13]: a1_rshifted = np.roll(a1, 1) In [14]: starts = a1 & ~a1_rshifted # it's True but the previous isn't In [15]: ends = ~a1 & a1_rshifted

其中

非零是每个 True 批次的开始(或分别是结束批次):

In [16]: np.nonzero(starts)[0], np.nonzero(ends)[0] Out[16]: (array([3, 6]), array([5, 9]))

并将它们压缩在一起:

In [17]: zip(np.nonzero(starts)[0], np.nonzero(ends)[0]) Out[17]: [(3, 5), (6, 9)]
    

3
投票
如果您有权访问 scipy 库:

您可以使用

scipy.ndimage.measurements.label 来识别任何非零值的区域。它返回一个数组,其中每个元素的值是原始数组中跨度或范围的 id。

然后您可以使用

scipy.ndimage.measurements.find_objects 返回提取这些范围所需的切片。您可以直接从这些切片访问开始/结束值。

在你的例子中:

import numpy from scipy.ndimage.measurements import label, find_objects data = numpy.array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0]) labels, number_of_regions = label(data) ranges = find_objects(labels) for identified_range in ranges: print(identified_range[0].start, identified_range[0].stop)
你应该看到:

3 5 6 9
希望这有帮助!


0
投票
而不是使用 np.roll,它有一个严重的滚动问题。你最好复印两份。一个带有右垫,另一个带有左垫。我需要这个来制作图像。

a = np.pad(im, ((0, 0), (0, 1)), constant_values=0) b = np.pad(im, ((0, 0), (1, 0)), constant_values=0) starts = a & ~b ends = ~a & b sx, sy = np.nonzero(starts) ex, ey = np.nonzero(ends)
批准的答案有一个问题,因为如果你以 True 结尾,它会被滚到前面并弄乱值。您确实想用 0 填充这些值。

然后您将找到 1 -> 0 转换和 0 -> 1 转换,并将它们放入您需要的格式。

© www.soinside.com 2019 - 2024. All rights reserved.