从NumPy 2D数组中删除重复的列和行

23 投票
6 回答
28550 浏览
提问于 2025-04-17 08:38

我正在使用一个二维数组来存储经度和纬度的配对。在某个时候,我需要把两个这样的二维数组合并在一起,然后去掉重复的条目。我一直在寻找一个类似于numpy.unique的函数,但一直没有找到。我想到的任何实现方式看起来都很“没效率”。比如,我尝试把数组转换成一个元组的列表,用集合去掉重复项,然后再转换回数组:

coordskeys = np.array(list(set([tuple(x) for x in coordskeys])))

有没有现成的解决方案,这样我就不用重新发明轮子了?

为了更清楚,我想要的是:

>>> a = np.array([[1, 1], [2, 3], [1, 1], [5, 4], [2, 3]])
>>> unique_rows(a)
array([[1, 1], [2, 3],[5, 4]])

顺便说一下,我本来想只用元组的列表,但这些列表太大了,导致我的4GB内存加4GB交换空间都不够用(numpy数组更节省内存)。

6 个回答

5

我的方法是把一个二维数组转换成一个一维的复杂数组,其中实部是第一列,虚部是第二列。然后使用np.unique。不过这个方法只适用于有两列的情况。

import numpy as np 
def unique2d(a):
    x, y = a.T
    b = x + y*1.0j 
    idx = np.unique(b,return_index=True)[1]
    return a[idx] 

举个例子 -

a = np.array([[1, 1], [2, 3], [1, 1], [5, 4], [2, 3]])
unique2d(a)
array([[1, 1],
       [2, 3],
       [5, 4]])
33

这样做就可以解决问题:

def unique_rows(a):
    a = np.ascontiguousarray(a)
    unique_a = np.unique(a.view([('', a.dtype)]*a.shape[1]))
    return unique_a.view(a.dtype).reshape((unique_a.shape[0], a.shape[1]))

举个例子:

>>> a = np.array([[1, 1], [2, 3], [1, 1], [5, 4], [2, 3]])
>>> unique_rows(a)
array([[1, 1],
       [2, 3],
       [5, 4]])
16

这里有一个想法,虽然需要花一点时间去实现,但速度可能会很快。我先给你讲解一维数组的情况,然后你可以自己想办法把它扩展到二维。下面这个函数可以找到一维数组中的唯一元素:

import numpy as np
def unique(a):
    a = np.sort(a)
    b = np.diff(a)
    b = np.r_[1, b]
    return a[b != 0]

要把它扩展到二维,你需要改动两个地方。首先,你得自己想办法进行排序,排序的关键是要确保两个相同的元素能够排在一起。其次,你需要做类似于 (b != 0).all(axis) 的操作,因为你想要比较整行或整列的内容。如果这些信息能让你入门,那就太好了。

更新:在Doug的帮助下,我觉得这个方法应该可以适用于二维情况。

import numpy as np
def unique(a):
    order = np.lexsort(a.T)
    a = a[order]
    diff = np.diff(a, axis=0)
    ui = np.ones(len(a), 'bool')
    ui[1:] = (diff != 0).any(axis=1) 
    return a[ui]

撰写回答