【问题标题】:Removing duplicate columns and rows from a NumPy 2D array从 NumPy 二维数组中删除重复的列和行
【发布时间】:2012-01-23 12:44:12
【问题描述】:

我正在使用二维形状数组来存储经度+纬度对。在某一时刻,我必须合并其中的两个二维数组,然后删除任何重复的条目。我一直在寻找类似于 numpy.unique 的函数,但我没有运气。我做过的任何实现 思考看起来非常“未优化”。例如,我正在尝试将数组转换为元组列表,使用 set 删除重复项,然后再次转换为数组:

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 RAM + 4Gb 交换空间(numpy 数组的内存效率更高)。

【问题讨论】:

标签: python numpy scipy duplicate-removal


【解决方案1】:

numpy_indexed 包(免责声明:我是它的作者)将 user545424 发布的解决方案包装在一个经过测试的漂亮界面中,以及许多相关功能:

import numpy_indexed as npi
npi.unique(coordskeys)

【讨论】:

    【解决方案2】:

    我的方法是将二维数组转换为一维复数数组,其中实部是第一列,虚部是第二列。然后使用 np.unique。虽然这只适用于 2 列。

    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]])
    

    【讨论】:

      【解决方案3】:

      这应该可以解决问题:

      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]])
      

      【讨论】:

      • @user100464,经过编辑,可以与转置数组一起使用。
      【解决方案4】:

      这是一个想法,它需要一些工作,但可能很快。我会给你 1d 的情况,让你弄清楚如何将它扩展到 2d。以下函数查找一维数组的唯一元素:

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

      现在要将其扩展到 2d,您需要更改两件事。您需要自己弄清楚如何进行排序,排序的重要一点是两个相同的条目最终彼此相邻。其次,您需要执行(b != 0).all(axis) 之类的操作,因为您想比较整行/列。让我知道这是否足以让您开始。

      更新:在 doug 的帮助下,我认为这应该适用于 2d 案例。

      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]
      

      【讨论】:

      • +1 刚刚发布了我的答案,然后阅读了你的答案——看起来我的答案是你的忠实 2D 实现——相同的功能序列(我什至一开始有一个行连接步骤,但是我将其删除并从原始数组中切出第一行。
      • 这个答案主要使用 numpy,所以 python2/3 应该不重要。如果它不适合你,可能还有其他事情发生。
      • 在 Python3 中为我工作。请注意,这不会保留顺序。
      • 请注意,lexsort 解决方案的支持列数有限
      【解决方案5】:
      >>> import numpy as NP
      >>> # create a 2D NumPy array with some duplicate rows
      >>> A
          array([[1, 1, 1, 5, 7],
                 [5, 4, 5, 4, 7],
                 [7, 9, 4, 7, 8],
                 [5, 4, 5, 4, 7],
                 [1, 1, 1, 5, 7],
                 [5, 4, 5, 4, 7],
                 [7, 9, 4, 7, 8],
                 [5, 4, 5, 4, 7],
                 [7, 9, 4, 7, 8]])
      
      >>> # first, sort the 2D NumPy array row-wise so dups will be contiguous
      >>> # and rows are preserved
      >>> a, b, c, d, e = A.T    # create the keys for to pass to lexsort
      >>> ndx = NP.lexsort((a, b, c, d, e))
      >>> ndx
          array([1, 3, 5, 7, 0, 4, 2, 6, 8])
      >>> A = A[ndx,]
      
      >>> # now diff by row
      >>> A1 = NP.diff(A, axis=0)
      >>> A1
          array([[0, 0, 0, 0, 0],
                 [4, 3, 3, 0, 0],
                 [0, 0, 0, 0, 0],
                 [0, 0, 0, 1, 0],
                 [0, 0, 1, 0, 0],
                 [2, 5, 0, 2, 1],
                 [0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0]])
      
      >>> # the index array holding the location of each duplicate row
      >>> ndx = NP.any(A1, axis=1)  
      >>> ndx
          array([False,  True, False,  True,  True,  True, False, False], dtype=bool)  
      
      >>> # retrieve the duplicate rows:
      >>> A[1:,:][ndx,]
          array([[7, 9, 4, 7, 8],
                 [1, 1, 1, 5, 7],
                 [5, 4, 5, 4, 7],
                 [7, 9, 4, 7, 8]])
      

      【讨论】:

      • Doug,我认为你已经接近了,但你会遇到麻烦,因为 NP.sort(A, axis=0) 独立地对每一列进行排序。尝试在以下两个数组上运行您的方法:[[0, 0], [1, 1], [2,2]][[0, 1], [1, 0], [2,2]]。我在我的答案中添加了一个排序函数,可以在排序时保持行的完整性。
      • 我不知道 lexsort,如果可以的话,我会把它包含在我的答案中
      • @Bago :绝对——无论如何,你首先解决了问题的核心,这就是为什么我对你的答案投了赞成票,并留下评论让人们知道我的答案只是一个几个小时后发布了你的修改版。
      【解决方案6】:

      既然你引用了 numpy.unique,你就不关心保持原来的顺序,对吗?转换成集合,去掉重复,然后返回列表是常用的成语:

      >>> x = [(1, 1), (2, 3), (1, 1), (5, 4), (2, 3)]
      >>> y = list(set(x))
      >>> y
      [(5, 4), (2, 3), (1, 1)]
      >>> 
      

      【讨论】:

      • 是的,顺序并不重要。组合 list + set 的解决方案是我在 OP 上用作示例的解决方案(我承认这很模糊)。它的问题是它使用列表,因此使用的内存很大,与我从一开始就使用列表而不是数组一样存在同样的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-08
      • 2012-06-26
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      相关资源
      最近更新 更多