按另一个矩阵排序在一个案例中有效但在另一个案例中失败

时间:2018-04-05 20:34:59

标签: python sorting numpy valueerror

我需要根据另一个矩阵中值的降序对矩阵进行排序。

E.g。在第一步中,我将得到以下矩阵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

要根据向量A对矩阵col_val进行排序,我认为我可以转置矩阵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中显示的示例中,排序似乎适用于具有多个相等条目的情况

1 个答案:

答案 0 :(得分:2)

您的怀疑是正确的,您无法使用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顾名思义将二进制向量包装到位字段中;它几乎相当于你手写的代码 - packbits8的块上运行,而右边的零填充有一个小的区别,所以例如[1, 1]将会到192,而不是3

np.argsort进行间接排序,因此它实际上不会移动其操作数A的元素,而只是将索引序列I写入A会对它进行排序A[I] == np.sort(A)。当我们想要根据其他类似的顺序对某些内容进行排序时,这非常有用。