快速高效地切片数组,避免删除操作。

3

我正在尝试获取数组A(N,3)的一部分(例如元素1-3和5-N),避免使用numpy.delete。下面是一个示例过程:

 [[1,2,3],[4,5,6],[7,8,9],[3,2,1]] ==>  [[1,2,3],[3,2,1]]

I was hoping to use something like

A[A != [1,2,3] ].reshape()

但是这样做会执行逐个元素的比较,因此会删除更多的元素。那该怎么办呢?我想到了这个方法,但似乎过于复杂且速度较慢:
A_removed = A[first_removed:last:removed,:] 
mask      = np.not_equal(A[:,None],A_removed)
mask      = np.logical_and.reduce(mask,1)
A         = A[mask].reshape()

有没有更快/更简洁的方法来做这件事?注意,假设 A 中的任意两个元素都不相等。

你能用言语解释一下如何获得预期的输出吗? - Divakar
也许根据那段复杂的代码,可以使用 A[~(A != [1,2,3]).all(1)] 或者 A[(A == [1,2,3]).any(1)] - Divakar
你的问题是要匹配给定值的任意顺序吗?如果是这样,我建议你使用集合操作或将值排序到临时变量中进行比较。 - Prune
说实话,这听起来像是numpy.delete的工作。你不太可能比numpy.delete更快地完成这个任务。最有可能的优化路径可能是重构你的计算以消除这个操作,而不是让这个操作变得更快。 - user2357112
1个回答

1

编辑

重新阅读问题后,我现在很确定OP想要的是我最初发布的相反情况。以下是如何获得它:

import numpy as np

def selectRow(arr, selrow):
    selset = set(selrow)
    return np.array([row for row in arr if selset == set(row)])
    
arr = np.array([
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [3,2,1]
])

selectRow(arr, [1,2,3])

输出:

array([[1, 2, 3],
       [3, 2, 1]])

目前我会保留原始回答,以防我错了。

原始回答

有序版本

只需要这样:

import numpy as np

def withoutRow(arr, badrow):
    return np.array([row for row in arr if not np.array_equal(row, badrow)])

然后您可以将其用作如下:
arr = np.array([
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [3,2,1]
])

withoutRow(arr, [1,2,3])

输出:

array([[4, 5, 6],
       [7, 8, 9],
       [3, 2, 1]])

withoutRow应该相当高效(特别是与布尔索引相比),因为只有一个循环(在原始数组的行上),并且您只需要构造一个新数组(返回值)。

无序版本

如果您想删除任何匹配坐标的点而不考虑坐标的顺序,则可以使用以下方法:

def withoutRowUnordered(arr, badrow):
    badset = set(badrow)
    return np.array([row for row in arr if badset != set(row)])

withoutRowUnordered(arr, [1,2,3])

输出:

array([[4, 5, 6],
       [7, 8, 9]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接