我想检查矩阵中是否有相同的行
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
您可以在 axis=0 上使用 np.unique
来获取唯一行。
return_counts=True
会return每行重复的次数。
设置条件 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)
--------------------------
解释
从 10,7 数组(10 行,7 列)中,您想要匹配元素,以便最终得到一个具有布尔值的 (10,10) 矩阵,该矩阵指示是否所有7 行中的元素匹配任何其他行中的任何元素。
mask = ~np.eye(arr.shape[0], dtype=bool)
是一个 10,10 形状的矩阵,沿对角线具有假值。这样做的原因是,因为您想忽略行与自身的比较。稍后会详细介绍。
从广播的布尔运算开始 - (arr[None,:,:] == arr[:,None,:])
。这会产生一个 10,10,7 布尔数组,该数组将每一行的元素与所有其他行进行比较(10 x 10 次比较,匹配 7 个值)。
现在,使用 .all(-1)
缩小最后一个轴并得到一个包含 True 的 10,10 矩阵,如果所有 7 个元素都匹配任何其他行,否则即使单个元素也为 false不一样。
接下来,如您所知,第 0 行将始终与第 0 行匹配,因此第 1 行将与第 1 行匹配。因此,此矩阵中的对角线始终为真。为了推断是否存在重复行,我们必须忽略对角线的真值。这可以通过在掩码(上面讨论的)和 10,10 布尔数组之间执行 &
(和)操作来完成。因此发生的唯一变化是对角线元素变为 False 而不是 True。
最后,您可以使用 .any()
将数组缩减为单个布尔值,即使新的 10,10 矩阵中的单个元素为真(这表明有一行 x 与行 y 完全匹配并且行 x 与行 y 不同,多亏了掩码)
我需要检查包含整数值的矩阵中是否有任何相同的行 例如:
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
您可以在 axis=0 上使用
np.unique
来获取唯一行。return_counts=True
会return每行重复的次数。设置条件
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)
--------------------------
解释
从 10,7 数组(10 行,7 列)中,您想要匹配元素,以便最终得到一个具有布尔值的 (10,10) 矩阵,该矩阵指示是否所有7 行中的元素匹配任何其他行中的任何元素。
mask = ~np.eye(arr.shape[0], dtype=bool)
是一个 10,10 形状的矩阵,沿对角线具有假值。这样做的原因是,因为您想忽略行与自身的比较。稍后会详细介绍。从广播的布尔运算开始 -
(arr[None,:,:] == arr[:,None,:])
。这会产生一个 10,10,7 布尔数组,该数组将每一行的元素与所有其他行进行比较(10 x 10 次比较,匹配 7 个值)。现在,使用
.all(-1)
缩小最后一个轴并得到一个包含 True 的 10,10 矩阵,如果所有 7 个元素都匹配任何其他行,否则即使单个元素也为 false不一样。接下来,如您所知,第 0 行将始终与第 0 行匹配,因此第 1 行将与第 1 行匹配。因此,此矩阵中的对角线始终为真。为了推断是否存在重复行,我们必须忽略对角线的真值。这可以通过在掩码(上面讨论的)和 10,10 布尔数组之间执行
&
(和)操作来完成。因此发生的唯一变化是对角线元素变为 False 而不是 True。最后,您可以使用
.any()
将数组缩减为单个布尔值,即使新的 10,10 矩阵中的单个元素为真(这表明有一行 x 与行 y 完全匹配并且行 x 与行 y 不同,多亏了掩码)