拆分 3D numpy 数组以获取具有满足条件的连续值的所有系列

Split a 3D numpy array to get all series with consecutive values that meet a condition

我想获得 3D 数组中沿轴 0 满足条件的所有数字序列。我正在尝试尽可能矢量化所有内容以避免极其低效的循环。

下面的代码是有效的,它以一个定义的数组为例,形状为(6, 2, 3)。它在其上应用一个掩码,由数组 b(相同维度)定义。

然后,我沿轴 0 对 3D 数组进行切片,这样我就有 2*3 个 1D 切片,从而获得 6 个形状为 (6,) 的 1D 数组。为此,我使用了一个循环,这显然会成为较大数组的效率问题。

然后我根据得到的掩码拆分我的数组,select(现在简单打印)至少有3个连续值满足b数组给定条件的系列。

import numpy as np

a = np.array([[[0.57337127, 0.7626088, 0.26965987],
               [0.66987041, 0.2914202, 0.62678441]],
              [[0.97442524, 0.61656519, 0.10544983],
               [0.05780219, 0.00381356, 0.57118615]],
              [[0.47069657, 0.36802822, 0.67483419],
               [0.32773146, 0.99773064, 0.56042508]],
              [[0.70984651, 0.25093198, 0.71911127],
               [0.05182876, 0.9463291, 0.7222756]],
              [[0.56736192, 0.62692889, 0.33814278],
               [0.72362855, 0.12885637, 0.44096788]],
              [[0.12706838, 0.90640269, 0.5126569],
               [0.62920448, 0.24502599, 0.26754067]]])

b = np.array([[[0.4, 0.4, 0.4],
               [0.4, 0.4, 0.4]],
              [[0.4, 0.4, 0.4],
               [0.4, 0.4, 0.4]],
              [[0.4, 0.4, 0.4],
               [0.4, 0.4, 0.4]],
              [[0.4, 0.4, 0.4],
               [0.4, 0.4, 0.4]],
              [[0.4, 0.4, 0.4],
               [0.4, 0.4, 0.4]],
              [[0.4, 0.4, 0.4],
               [0.4, 0.4, 0.4]]])

# these two loops i and j are very inefficient 
for i in range(a.shape[1]):
    for j in range(a.shape[2]):
        print(i, j)
        aij = a[:, i, j]
        bij = b[:, i, j]
        mask = aij <= bij
        split_indices = np.where(mask)[0]
        for subarray in np.split(aij, split_indices + 1):
            if len(subarray) > 3:
                print(subarray[:-1])

现在,这行得通了。 但是,我的实际数据(数组 a 和 b)的形状为 ~(500, 800, 1500),这意味着循环变得有问题(相当昂贵)。

你能想出一种方法来进一步矢量化它吗?我试图获得一个 3D 蒙版并按 3D 方式进行拆分,但这会导致沿轴 1 和轴 2 的拆分大小不相等,这是一个问题(也是 np.split 仅采用 0 或 1-D 的原因索引列表。

您可以遍历轴 0,而不是在轴 (1,2) 上循环,以迭代检查掩码是否适用于连续的元素。根据您最终想要实现的目标,最多需要 n 次迭代(其中 n 是您拥有的最长序列)。

例如,如果您只想确定满足 mask 的至少 3 个连续元素的任何有效序列的起始元素,您可以这样做:

mask = a > b
runs = np.zeros_like(mask, dtype=bool)
runs[:-2] = mask[:-2] & mask[1:-1] & mask[2:]

在您的示例中,这会产生:

>>> runs
array([[[ True, False, False],
    [False, False,  True]],
   [[ True, False, False],
    [False, False,  True]],
   [[ True, False, False],
    [False, False,  True]],
   [[False, False, False],
    [False, False, False]],
   [[False, False, False],
    [False, False, False]],
   [[False, False, False],
    [False, False, False]]])

在这里,对于长度至少为 3 的有效序列的所有起始元素,runs 的计算结果为 True。因为我不确定一旦确定它们后您想做什么,我是留在这里。但希望很清楚如何从这里开始概括您要尝试做的事情。