【问题标题】:Finding indices of non-unique elements in Numpy array在 Numpy 数组中查找非唯一元素的索引
【发布时间】:2015-12-06 21:39:59
【问题描述】:

我找到了其他方法,例如this,可以从数组中删除重复元素。我的要求略有不同。如果我开始:

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

我想结束:

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

这就是我最终想要的结果,但还有一个额外的要求。我还想存储要丢弃或保留的索引数组(例如numpy.take)。

我正在使用 Numpy 1.8.1

【问题讨论】:

  • 您可以使用建议的方法计算每行出现的次数,例如here 和here。我认为这就是您的问题所在。
  • @ajcr 我不能使用return_counts 所以#1 不适合我。不幸的是#2似乎需要排序数组,我需要保留顺序。
  • @codedog 任何一个答案都有帮助吗?如果没有,您能否告诉我们您还在寻找什么,

标签: python arrays python-2.7 numpy


【解决方案1】:

我们希望找到在您的数组中不重复的行,同时保留顺序。

我使用这个solution 将a 的每一行组合成一个元素,这样我们就可以使用np.unique(,return_index=True, return_inverse= True) 找到唯一的行。然后,我修改了这个function 以使用索引和逆输出唯一行的计数。从那里,我可以选择所有具有counts == 1 的唯一行。

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

#use a flexible data type, np.void, to combine the columns of `a`
#size of np.void is the number of bytes for an element in `a` multiplied by number of columns
b = a.view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
_, index, inv = np.unique(b, return_index = True, return_inverse = True)

def return_counts(index, inv):
    count = np.zeros(len(index), np.int)
    np.add.at(count, inv, 1)
    return count

counts = return_counts(index, inv)

#if you want the indices to discard replace with: counts[i] > 1
index_keep = [i for i, j in enumerate(index) if counts[i] == 1]

>>>a[index_keep]
array([[2, 3, 4],
   [3, 2, 1],
   [3, 4, 5]])

#if you don't need the indices and just want the array returned while preserving the order
a_unique = np.vstack(a[idx] for i, idx in enumerate(index) if counts[i] == 1])
>>>a_unique
array([[2, 3, 4],
   [3, 2, 1],
   [3, 4, 5]])

对于 np.version >= 1.9

b = a.view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
_, index, counts = np.unique(b, return_index = True, return_counts = True)

index_keep = [i for i, j in enumerate(index) if counts[i] == 1]
>>>a[index_keep]
array([[2, 3, 4],
   [3, 2, 1],
   [3, 4, 5]])

【讨论】:

  • 除了请求排除 [1,2,3] 因为它不止一次出现
  • @Dan Patterson 感谢您指出,我已经编辑了我的解决方案。
  • 昨天我发现我们已经在一个 C 扩展中实现了这个。我没有明确测试过这个解决方案,但它看起来与这里实现的非常相似。这就是我接受它作为解决方案的原因。谢谢。
【解决方案2】:

您可以按照以下方式进行:

# Assuming your array is a
uniq, uniq_idx, counts = np.unique(a, axis=0, return_index=True, return_counts=True)

# to return the array you want
new_arr = uniq[counts == 1]

# The indices of non-unique rows
a_idx = np.arange(a.shape[0]) # the indices of array a
nuniq_idx = a_idx[np.in1d(a_idx, uniq_idx[counts==1], invert=True)] 

你得到:

#new_arr
array([[2, 3, 4],
       [3, 2, 1],
       [3, 4, 5]])

# nuniq_idx
array([0, 2])

【讨论】:

    【解决方案3】:

    如果要删除重复版本中存在的元素的所有实例,可以遍历数组,找到多个版本中存在的元素的索引,最后删除这些:

    # The array to check:
    array = numpy.array([[1, 2, 3],
            [2, 3, 4],
            [1, 2, 3],
            [3, 2, 1],
            [3, 4, 5]])
    
    # List that contains the indices of duplicates (which should be deleted)
    deleteIndices = []
    
    for i in range(0,len(array)): # Loop through entire array
        indices = range(0,len(array)) # All indices in array
        del indices[i] # All indices in array, except the i'th element currently being checked
    
    for j in indexes: # Loop through every other element in array, except the i'th element, currently being checked
        if(array[i] == array[j]).all(): # Check if element being checked is equal to the j'th element
            deleteIndices.append(j) # If i'th and j'th element are equal, j is appended to deleteIndices[]
    
    # Sort deleteIndices in ascending order:
    deleteIndices.sort()
    
    # Delete duplicates
    array = numpy.delete(array,deleteIndices,axis=0)
    

    这个输出:

    >>> array
    array([[2, 3, 4],
           [3, 2, 1],
           [3, 4, 5]])
    
    >>> deleteIndices
    [0, 2]
    

    就像您删除重复项并获得要丢弃的索引列表一样。

    【讨论】:

      【解决方案4】:

      numpy_indexed 包(免责声明:我是它的作者)可用于以矢量化方式解决此类问题:

      index = npi.as_index(arr)
      keep = index.count == 1
      discard = np.invert(keep)
      print(index.unique[keep])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-24
        • 2014-06-09
        • 2019-07-12
        • 1970-01-01
        • 1970-01-01
        • 2015-03-07
        • 2017-12-01
        • 2015-06-16
        相关资源
        最近更新 更多