首页 > 解决方案 > 比较数组中的行值并删除具有几乎相同值的行

问题描述

我有以下数组:

a= [[2,3,50], [5,6,5], [8,10,5], [1,3,51] , [8,10,12]]

我想比较行并删除具有几乎相同值的行。例如 [2,3,50] 和 [1,3,51] 几乎相同(每个值的差异小于 1)。

最后,我应该得到以下数组:

a= [[2,3,50], [5,6,5], [8,10,5], [8,10,12]]

其中 [1,3,51] 已被删除。在 Python 中是否有有效的方法来避免多个循环?最好的

标签: pythonarraysnumpy

解决方案


我们可以在两个版本的第一个轴上执行外减法,a然后得到绝对值并检查沿公共轴的所有值是否小于或等于 的阈值1。这会给我们一个2D面具。我们需要选择上三角蒙版,以确保附近的对不会被多次考虑。重置对应于自己案例的对角线。最后,检查每个 col 中是否至少有 match,这是我们需要删除的 closeby。因此,反转掩码并选择行 off a

实施将是 -

a[~np.triu((np.abs(a[:,None,:]-a)<=1).all(2),1).any(0)]

逐步执行的示例运行应该有助于澄清。

输入数组:

In [112]: a
Out[112]: 
array([[ 2,  3, 50],
       [ 5,  6,  5],
       [ 8, 10,  5],
       [ 1,  3, 51],
       [ 8, 10, 12]])

脚步 :

In [114]: (np.abs(a[:,None,:]-a)<=1).all(2)
Out[114]: 
array([[ True, False, False,  True, False],
       [False,  True, False, False, False],
       [False, False,  True, False, False],
       [ True, False, False,  True, False],
       [False, False, False, False,  True]])

In [115]: np.triu((np.abs(a[:,None,:]-a)<=1).all(2),1)
Out[115]: 
array([[False, False, False,  True, False],
       [False, False, False, False, False],
       [False, False, False, False, False],
       [False, False, False, False, False],
       [False, False, False, False, False]])

In [116]: np.triu((np.abs(a[:,None,:]-a)<=1).all(2),1).any(0)
Out[116]: array([False, False, False,  True, False])

In [117]: ~np.triu((np.abs(a[:,None,:]-a)<=1).all(2),1).any(0)
Out[117]: array([ True,  True,  True, False,  True])

In [118]: a[~np.triu((np.abs(a[:,None,:]-a)<=1).all(2),1).any(0)]
Out[118]: 
array([[ 2,  3, 50],
       [ 5,  6,  5],
       [ 8, 10,  5],
       [ 8, 10, 12]])

为了再做一轮验证,让我们将最后一行设置为倒数第二行的另一个 closeby。这也应该导致最后一行被删除。因此 -

In [120]: a[-1] = [0,3,52]

In [122]: a
Out[122]: 
array([[ 2,  3, 50],
       [ 5,  6,  5],
       [ 8, 10,  5],
       [ 1,  3, 51],
       [ 0,  3, 52]])

In [123]: a[~np.triu((np.abs(a[:,None,:]-a)<=1).all(2),1).any(0)]
Out[123]: 
array([[ 2,  3, 50],
       [ 5,  6,  5],
       [ 8, 10,  5]])

具有单循环以提高内存效率

我们可以使用一个循环来节省内存,从而在这方面提高效率,并在过程中使用切片 -

n = len(a)
mask = np.zeros(n, dtype=bool)
for i in range(n-1):
    mask[i+1:] |= (np.abs(a[i+1:]-a[i])<=1).all(1)
out = a[~mask]

推荐阅读