【问题标题】:check if the rows from a set of indices are duplicates or not and reconstruction检查一组索引中的行是否重复并重建
【发布时间】:2019-06-28 04:34:57
【问题描述】:

我有一个二维二进制数组,其中的值只能取 0 和 1。 我有一组索引来检查这些索引的二进制矩阵的条目是否重复。我想获得删除重复行的矩阵和一组重复索引。

例如,

>>>> a
array([[1, 0, 1, 0],
       [0, 0, 1, 1],
       [1, 0, 1, 0],
       [0, 0, 1, 1],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
])

我得到一组索引 (0,2,3,4,6,7)。从集合中,对应于 (0,2) 和 (4,6,7) 的行是重复的。我想要删除重复项的结果矩阵(如下所示)

>>>> b
array([[1, 0, 1, 0],
       [0, 0, 1, 1],
       [0, 0, 1, 1],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
])

以及从“b”重构矩阵“a”的方法

【问题讨论】:

    标签: python-2.7 numpy indexing unique


    【解决方案1】:

    如果输出数组中的顺序不相关,那么您可能只使用Eelco Hoogendoorn's answer。但是,如果您想保持与原始数组中相同的相对顺序,这是另一种可能的方法。

    import numpy as np
    
    a = np.array([
        [1, 0, 1, 0],
        [0, 0, 1, 1],
        [1, 0, 1, 0],
        [0, 0, 1, 1],
        [1, 1, 1, 0],
        [1, 1, 1, 0],
        [1, 1, 1, 0],
        [1, 1, 1, 0],
    ])
    idx = np.array([0, 2, 3, 4, 6, 7])
    # Make an array of row numbers
    r = np.arange(len(a))
    # Replace row numbers in idx with -1
    # (use assume_unique only if indices in idx are unique)
    r[np.isin(r, idx, assume_unique=True)] = -1
    # Add the column to the array
    a2 = np.concatenate([a, r[:, np.newaxis]], axis=-1)
    # Find unique indices and inverse indices
    _, uniq_idx, inv_idx = np.unique(a2, return_index=True, return_inverse=True, axis=0)
    # Sort indices to make output array and inverse indices
    s = np.argsort(uniq_idx)
    a_uniq = a[uniq_idx[s]]
    inv_idx = s[inv_idx]
    print(a_uniq)
    # [[1 0 1 0]
    #  [0 0 1 1]
    #  [0 0 1 1]
    #  [1 1 1 0]
    #  [1 1 1 0]]
    print(np.all(a_uniq[inv_idx] == a))
    # True
    

    编辑:一些进一步的解释。

    上述解决方案中的想法是应用np.unique,但在某种程度上,idx 中未包含的行不受其影响。为此,您只需在每一行中添加一个新数字。对于idx 中包含的行,此编号将始终为-1,而对于其余行,每个行将是不同的编号。这样一来,np.unique 不可能删除不在idx 中的行。为此,我构建了r,首先使用np.arange(len(a)),它为每行提供一个数字:

    [0 1 2 3 4 5 6 7]
    

    然后我检查哪些在idxnp.isin(r, idx, assume_unique=True) 中(assume_unique 只能在idx 中的元素保证是唯一的情况下使用),所以r[np.isin(r, idx, assume_unique=True)] = -1 将把所有索引idx进入-1:

    [-1  1 -1 -1 -1  5 -1 -1]
    

    作为新列添加到aa2

    [[ 1  0  1  0 -1]
     [ 0  0  1  1  1]
     [ 1  0  1  0 -1]
     [ 0  0  1  1 -1]
     [ 1  1  1  0 -1]
     [ 1  1  1  0  5]
     [ 1  1  1  0 -1]
     [ 1  1  1  0 -1]]
    

    现在只需将np.unique 应用于a2。正如预期的那样,只有idx 中的行可能会被删除。但是,由于我们要保持原来的相对顺序,我们不能使用np.unique 的输出,因为它是排序的。我们使用return_indexreturn_inverse 来获取构成唯一行数组的索引和使您返回原始数组的索引,并实际丢弃新数组。

    要形成最终的数组,您需要对uniq_idx 进行排序以保持相对顺序,然后对inv_idx 进行相应的排序。 np.argsort 为您提供将uniq_idx 排序为s 的索引。 uniq_idx[s] 只是排序后的唯一行索引数组,s[inv_idx] 会将inv_idx 中的每个反向索引映射到resorted 数组中的相应索引。所以,最后,a[uniq_idx[s]] 为您提供了输出数组,而新的inv_idx 将您带回原来的数组。

    【讨论】:

    • @Shew 我已经添加了一些解释,希望对您有所帮助。
    【解决方案2】:

    感觉您可以在更高层次上表述您的问题以获得更优雅的解决方案;但这似乎解决了上述字面问题。

    idx = [0,2,3,4,6,7]
    b = np.concatenate([np.unique(a[idx], axis=0), np.delete(a, idx, axis=0)], axis=0)
    

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-05
      • 2018-11-13
      • 2018-07-19
      • 2012-11-01
      • 1970-01-01
      相关资源
      最近更新 更多