一个大型 numpy 数组(5 列 300 万行)——如何选择同时满足多个条件的行? Python 3.8.8

One large numpy array (3mil rows on 5 columns) - how to pick rows that meet several conditions at the same time? Python 3.8.8

        def func(data):
            A = np.zeros([len(data), 5], np.int16)
            for i in range(len(data)):
                if(data[i, 1] >= -10 and data[i, 1] <= -13 and
                   data[i, 3] >= -20 and data[i, 3] <= -22):
                    A[i] = data[i]
                    
                elif(data[i, 1] >= -16 and data[i, 1] <= -19 and
                   data[i, 3] >= -24 and data[i, 3] <= --30):
                    A[i] = data[i]
                
                .... (for another similar 8 elif conditions)
                
                else:
                    continue

            return A[~np.all(A == 0, axis=1)]
        func(data)

问题: 我有一个大的 NumPy 数组,我需要提取满足这些条件的整行(不仅仅是索引或其值)。代码确实 运行 但速度很慢。这不是问题,但我必须阅读另外 800 个文件,然后执行其他任务。

如何优化这个功能? 提前谢谢你。

我已经制作了一个您可以尝试的工作版本。它摆脱了 for 循环,并且不需要您创建一个与 data 大小相同的全新数组 A;在我的版本中,A 从 0 行开始,然后根据需要添加,这应该有助于节省 space。该函数也在某种程度上进行了矢量化,这意味着我不会手动遍历每一行。

def func(data):
    # The array A must have the same number of columns as the data array. If you know this beforehand, then just use that; otherwise, replace 5 with data.shape[1].
    A = np.zeros((0,5))

    # mask1 contains the indices where these conditions are all met. After the mask is found, the rows in data with indices in mask1 are essentially appended to A.
    mask1 = np.where((data[:,1] >= -10) & (data[:,1] <= -13) & (data[:,3] >= -20) & (data[:,3] <= -22))
    A = np.concatenate((A, data[mask1]), axis=0)

    # Do the same for all the other conditions.
    mask2 = np.where((data[:,1] <= -19) & (data[:,3] >= -24) & (data[:,3] <= -30))
    A = np.concatenate((A, data[mask2]), axis=0)

    .... (for all other conditions)

    return A

还有一件事:我对 data[i, 1] >= -10 and data[i, 1] <= -13 如何计算为 True 感到有点困惑,因为 -13 小于 -10.Same 和 data[i, 3] >= -20 and data[i, 3] <= -22。也许您不小心翻转了标志,或者需要切换到 >=<= 标志?

你有一个错字(--30 而不是 -30),以防你错过了。我并不是想吹毛求疵,我只是不想让你陷入困境,为什么你的代码在你 运行 时不工作。对不起,如果我表现得很刻薄,我不想成为。

无论如何,如果您需要任何说明,请告诉我!

P.S。我为 side-scrolling 感到非常抱歉;我不确定如何修复它。

我的解决方案与 AJH 非常接近,但我相信它更简单一些,您不需要在内存中保留完整尺寸的 A 帧。不确定它有多大变化,但它占用的内存少了一点。

def func(data):
    condition_1 = ((data[:, 1] <= -10) & (data[:, 1] >= -13) & (data[:, 3] <= -20) & (data[:, 3] >= -22))
    condition_2 = ((data[:, 1] <= -16) & (data[:, 1] >= -19) & (data[:, 3] <= -24) & (data[:, 3] >= -30))
    mask = (condition_1 | condition_2)
    return data[mask]

然后只需添加您需要的所有条件即可。 有关 &and|or 的信息,虽然我发现完整关键字更易于使用,但实际上它不适用于 numpy arrays