我想检查矩阵中是否有相同的行

I want to check if there are any identical rows in a matrix

我需要检查包含整数值的矩阵中是否有任何相同的行 例如:

    A = [[ 2  0  0  0  0  0  0] 
        [ 2  3  5  0  0  0  0]
        [ 2  3  0  0  0  0  0]
        [ 2  0  5  7  0  0  0]
        [ 2  0  5  0  8  0 10]
        [ 2  3  5  0  0  9  0]
        [ 0  0  0  7  8  9  0]
        [ 0  0  5  7  8  9  0]
        [ 0  0  0  7  8  9  0]
        [ 0  0  5  0  0  0 10]]

这必须 return : 正确

但在其他例子中:

   B = [[ 2  0  0  0  0  0  0] 
        [ 2  3  5  0  0  0  0]
        [ 2  3  0  0  0  0  0]
        [ 2  0  5  7  0  0  0]
        [ 2  0  5  0  8  0 10]
        [ 2  3  5  0  0  9  0]
        [ 0  0  1  7  8  9  0]
        [ 0  0  5  7  8  9  0]
        [ 0  0  0  7  8  9  0]
        [ 0  0  5  0  0  0 10]]

这必须 return :

方法一:使用np.unique

  1. 您可以在 axis=0 上使用 np.unique 来获取唯一行。

  2. return_counts=True会return每行重复的次数。

  3. 设置条件 c>1 并检查是否有任何行与该条件匹配 .any() 会给你想要的结果。

def is_dup_simple(arr):
    u, c = np.unique(arr, axis=0, return_counts=True)
    return (c>1).any()

print(is_dup_simple(A))
print(is_dup_simple(B))
True
False

方法 2:广播

下面介绍了如何使用广播操作来完成此操作。这是一个稍微长一点的方法,但是让你对这个方法非常灵活(例如,在不同的数组之间找到重复项)

def is_dup(arr):
    mask = ~np.eye(arr.shape[0], dtype=bool)
    out = ((arr[None,:,:] == arr[:,None,:]).all(-1)&mask).any()
    return out

print(is_dup(A))
print(is_dup(B))
True
False

逐步广播table-

arr[None,:,:] -> 1 , 10, 7 (adding new first axis)
arr[:,None,:] -> 10, 1 , 7 (adding new second axis)
--------------------------
     ==       -> 10, 10, 7 (compare elements row-wise)
   all(-1)    -> 10, 10    (compare rows x rows)
   & mask     -> 10, 10    (diagonals false)
   any()      -> 1         (reduce to single bool)
--------------------------

解释

  1. 从 10,7 数组(10 行,7 列)中,您想要匹配元素,以便最终得到一个具有布尔值的 (10,10) 矩阵,该矩阵指示是否所有7 行中的元素匹配任何其他行中的任何元素。

  2. mask = ~np.eye(arr.shape[0], dtype=bool) 是一个 10,10 形状的矩阵,沿对角线具有假值。这样做的原因是,因为您想忽略行与自身的比较。稍后会详细介绍。

  3. 从广播的布尔运算开始 - (arr[None,:,:] == arr[:,None,:])。这会产生一个 10,10,7 布尔数组,该数组将每一行的元素与所有其他行进行比较(10 x 10 次比较,匹配 7 个值)。

  4. 现在,使用 .all(-1) 缩小最后一个轴并得到一个包含 True 的 10,10 矩阵,如果所有 7 个元素都匹配任何其他行,否则即使单个元素也为 false不一样。

  5. 接下来,如您所知,第 0 行将始终与第 0 行匹配,因此第 1 行将与第 1 行匹配。因此,此矩阵中的对角线始终为真。为了推断是否存在重复行,我们必须忽略对角线的真值。这可以通过在掩码(上面讨论的)和 10,10 布尔数组之间执行 &(和)操作来完成。因此发生的唯一变化是对角线元素变为 False 而不是 True。

  6. 最后,您可以使用 .any() 将数组缩减为单个布尔值,即使新的 10,10 矩阵中的单个元素为真(这表明有一行 x 与行 y 完全匹配并且行 x 与行 y 不同,多亏了掩码)