按另一个矩阵排序在一种情况下有效但在另一种情况下失败
Sorting by another matrix works in one case but fails for another
我需要根据另一个矩阵中值的降序对矩阵进行排序。
例如在第一步中,我将有以下矩阵 A
:
1 0 1 0 1
0 1 0 1 0
0 1 0 1 1
1 0 1 0 0
然后对于我正在执行的过程,我需要将矩阵的行作为二进制数并按二进制值的降序对它们进行排序。
我正在按以下方式执行此操作:
for i in range(0,num_rows):
for j in range(0,num_cols):
row_val[i] = row_val[i] + A[i][j] * (2 ** (num_cols - 1 - j))
这为我提供了一个 4x1 向量 row_val
,具有以下值:
21
10
11
20
现在我根据row_val
按
对矩阵的行进行排序
A = [x for _,x in sorted(zip(row_val,A),reverse=True)]
这很好用我得到了矩阵 A
:
1 0 1 0 1
1 0 1 0 0
0 1 0 1 1
0 1 0 1 0
但是现在我需要对列应用相同的过程。所以我用列的二进制值计算 col_val
向量:
12
3
12
3
3
根据向量 col_val
对矩阵 A
进行排序 我想我可以转置矩阵 A
然后像以前一样做:
At = np.transpose(A)
At = [y for _,y in sorted(zip(col_val,At),reverse=True)]
不幸的是,这失败并显示错误消息
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
我怀疑这可能是因为向量 col_val
中有多个条目具有相同的值,但是在 another question 中显示的示例中,排序似乎适用于具有多个条目的情况相等的条目。
您的怀疑是正确的,您不能使用 Python 内置 sorted
对多维 numpy 数组进行排序,因为比较两行,比方说,将产生一行真值而不是单身
A[0] < A[1]
# array([False, True, False, True, False])
所以 sorted
无法判断哪个应该在另一个之前。
在您的第一个示例中,这被元组的字典顺序所掩盖:因为元组是从左到右比较的,并且因为 row_val
具有唯一条目,所以比较从不查看第二个元素。
但是在你的第二个例子中,因为一些 col_val
条目是相等的,所以比较将在 At
中寻找决胜局,这是异常发生的地方。
这是一个使用 numpy 方法的工作方法:
A[np.argsort(np.packbits(A, axis=1).ravel())[::-1]]
# array([[1, 0, 1, 0, 1],
# [1, 0, 1, 0, 0],
# [0, 1, 0, 1, 1],
# [0, 1, 0, 1, 0]])
A[:, np.argsort(np.packbits(A, axis=0).ravel())[::-1]]
# array([[1, 1, 1, 0, 0],
# [0, 0, 0, 1, 1],
# [1, 0, 0, 1, 1],
# [0, 1, 1, 0, 0]])
解释:
np.packbits
顾名思义就是将二进制向量打包成位域;它几乎等同于您的 hand-written 代码 - 有一个小区别,即 packbits
对 8
的块进行操作,并在右侧填充零,例如 [1, 1]
将转到 192
,而不是 3
。
np.argsort
进行间接排序,因此它实际上并不移动其操作数 A
的元素,而只是将索引序列 I
写入 A
会对它进行排序 A[I] == np.sort(A)
。当我们想要根据其他事物的顺序对某些事物进行排序时(如本例),这很有用。
我需要根据另一个矩阵中值的降序对矩阵进行排序。
例如在第一步中,我将有以下矩阵 A
:
1 0 1 0 1
0 1 0 1 0
0 1 0 1 1
1 0 1 0 0
然后对于我正在执行的过程,我需要将矩阵的行作为二进制数并按二进制值的降序对它们进行排序。
我正在按以下方式执行此操作:
for i in range(0,num_rows):
for j in range(0,num_cols):
row_val[i] = row_val[i] + A[i][j] * (2 ** (num_cols - 1 - j))
这为我提供了一个 4x1 向量 row_val
,具有以下值:
21
10
11
20
现在我根据row_val
按
A = [x for _,x in sorted(zip(row_val,A),reverse=True)]
这很好用我得到了矩阵 A
:
1 0 1 0 1
1 0 1 0 0
0 1 0 1 1
0 1 0 1 0
但是现在我需要对列应用相同的过程。所以我用列的二进制值计算 col_val
向量:
12
3
12
3
3
根据向量 col_val
对矩阵 A
进行排序 我想我可以转置矩阵 A
然后像以前一样做:
At = np.transpose(A)
At = [y for _,y in sorted(zip(col_val,At),reverse=True)]
不幸的是,这失败并显示错误消息
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
我怀疑这可能是因为向量 col_val
中有多个条目具有相同的值,但是在 another question 中显示的示例中,排序似乎适用于具有多个条目的情况相等的条目。
您的怀疑是正确的,您不能使用 Python 内置 sorted
对多维 numpy 数组进行排序,因为比较两行,比方说,将产生一行真值而不是单身
A[0] < A[1]
# array([False, True, False, True, False])
所以 sorted
无法判断哪个应该在另一个之前。
在您的第一个示例中,这被元组的字典顺序所掩盖:因为元组是从左到右比较的,并且因为 row_val
具有唯一条目,所以比较从不查看第二个元素。
但是在你的第二个例子中,因为一些 col_val
条目是相等的,所以比较将在 At
中寻找决胜局,这是异常发生的地方。
这是一个使用 numpy 方法的工作方法:
A[np.argsort(np.packbits(A, axis=1).ravel())[::-1]]
# array([[1, 0, 1, 0, 1],
# [1, 0, 1, 0, 0],
# [0, 1, 0, 1, 1],
# [0, 1, 0, 1, 0]])
A[:, np.argsort(np.packbits(A, axis=0).ravel())[::-1]]
# array([[1, 1, 1, 0, 0],
# [0, 0, 0, 1, 1],
# [1, 0, 0, 1, 1],
# [0, 1, 1, 0, 0]])
解释:
np.packbits
顾名思义就是将二进制向量打包成位域;它几乎等同于您的 hand-written 代码 - 有一个小区别,即 packbits
对 8
的块进行操作,并在右侧填充零,例如 [1, 1]
将转到 192
,而不是 3
。
np.argsort
进行间接排序,因此它实际上并不移动其操作数 A
的元素,而只是将索引序列 I
写入 A
会对它进行排序 A[I] == np.sort(A)
。当我们想要根据其他事物的顺序对某些事物进行排序时(如本例),这很有用。