【问题标题】:finding identical rows and columns in a numpy array在 numpy 数组中查找相同的行和列
【发布时间】:2021-04-08 15:28:18
【问题描述】:

我有一个 nxn 元素的布尔数组,我想检查是否有任何行与另一行相同。如果有任何相同的行,我想检查相应的列是否也相同。

这是一个例子:

A=np.array([[0, 1, 0, 0, 0, 1],
            [0, 0, 0, 1, 0, 1],
            [0, 1, 0, 0, 0, 1],
            [1, 0, 1, 0, 1, 1],
            [1, 1, 1, 0, 0, 0],
            [0, 1, 0, 1, 0, 1]])

我想让程序发现第一行和第三行相同,然后检查第一列和第三列是否也相同;在这种情况下,它们是。

【问题讨论】:

  • 性能对你来说重要吗?
  • 不要太多,因为数组很小

标签: python arrays numpy


【解决方案1】:

你可以使用np.array_equal():

for i in range(len(A)):  # generate pairs
    for j in range(i + 1, len(A)): 
        if np.array_equal(A[i], A[j]):  # compare rows
            if np.array_equal(A[:,i], A[:,j]):  # compare columns
                print(i, j)
        else:
            pass

或使用combinations():

import itertools

for pair in itertools.combinations(range(len(A)), 2):
    if np.array_equal(A[pair[0]], A[pair[1]]) and np.array_equal(A[:,pair[0]], A[:,pair[1]]):  # compare columns
        print(pair)

【讨论】:

    【解决方案2】:

    从将np.unique 应用于二维数组并让它返回唯一对的典型方式开始:

    def unique_pairs(arr):
        uview = np.ascontiguousarray(arr).view(np.dtype((np.void, arr.dtype.itemsize * arr.shape[1])))
        uvals, uidx = np.unique(uview, return_inverse=True)
        pos = np.where(np.bincount(uidx) == 2)[0]
    
        pairs = []
        for p in pos:
            pairs.append(np.where(uidx==p)[0])
    
        return np.array(pairs)
    

    然后我们可以执行以下操作:

    row_pairs = unique_pairs(A)
    col_pairs = unique_pairs(A.T)
    
    for pair in row_pairs:
        if np.any(np.all(pair==col_pairs, axis=1)):
            print pair
    
    >>> [0 2]
    

    当然还有很多优化要做,但重点是使用np.unique。与其他方法相比,此方法的效率在很大程度上取决于您如何定义“小”数组。

    【讨论】:

      【解决方案3】:

      既然你说性能并不重要,这里有一个不是非常 numpythonic 的蛮力解决方案:

      >>> n = len(A)
      >>> for i1, row1 in enumerate(A):
      ...     offset = i1 + 1  # skip rows already compared 
      ...     for i2, row2 in enumerate(A[offset:], start=offset):
      ...         if (row1 == row2).all() and (A.T[i1] == A.T[i2]).all():
      ...             print i1, i2
      ...             
      0 2
      

      可能是 O(n^2)。我使用转置数组A.T 来检查列是否相等。

      【讨论】:

        【解决方案4】:

        对于小型数组,另一种不依赖 Python 循环的方法是通过 NumPy 广播。

        bool_array = np.logical_not(np.logical_xor(A[:,np.newaxis,:], A[np.newaxis,:,:])) # XNOR for comparison
        matches_array = np.sum(bool_array, axis=2)  # count total matches for all elements in a row
        row1, row2 = np.where(matches_array == A.shape[1]) # identical row = all elements in a row match
        row1, row2 = row1[row2 > row1], row2[row2 > row1]  # filter self & duplicated comparisons
        column_match = np.all(A[:,row1] == A[:,row2], axis=0)  # check if the corresponding columns are identical
        for r1, r2, c in zip(row1, row2, column_match):
            print("Row %d and row %d : Column identical: %s" % (r1, r2, c))
        

        如前所述,这种方法在 A 变大时不起作用,因为它在计算过程中需要 O(n^3) 内存存储(由于bool_array

        【讨论】:

          猜你喜欢
          • 2018-12-23
          • 2010-11-07
          • 2017-12-23
          • 1970-01-01
          • 2023-03-08
          • 2019-03-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多