根据对角线条目对矩阵进行排序

Kri*_*wan 5 python sorting numpy matrix python-3.x

首先,我想指出我的问题与这个问题不同:Sort a numpy matrix based on its对角线

\n\n

问题如下:\n假设我有一个 numpy 矩阵

\n\n
A=\n\n5 7 8\n\n7 2 9\n\n8 9 3\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想根据矩阵的对角线对矩阵进行排序,然后根据它重新排列矩阵元素。这样现在

\n\n
sorted_A:\n\n2 9 7\n\n9 3 8\n\n7 8 5\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意:

\n\n

(1). 对角线已排序

\n\n

(2)。其他元素(非对角线)由它重新调整。怎么办?\n因为 diag(A)= [5,2,3] & diag(sorted_A)=[2,3,5] \n所以行/列索引 A=[0,1,2] 变为 [1,2, 0]在sorted_A中。

\n\n

到目前为止,我使用蛮力提取对角线元素,获取索引 O(N\xc2\xb2),然后重新排列矩阵(另一个 O(N\xc2\xb2))。我想知道是否有任何有效/优雅的方法来做到这一点。我感谢我能得到的所有帮助。

\n

hpa*_*ulj 2

根据对角线值对行进行排序很容易:

In [192]: A=np.array([[5,7,8],[7,2,9],[8,9,3]])
In [193]: A
Out[193]: 
array([[5, 7, 8],
       [7, 2, 9],
       [8, 9, 3]])
In [194]: np.diag(A)
Out[194]: array([5, 2, 3])
In [195]: idx=np.argsort(np.diag(A))
In [196]: idx
Out[196]: array([1, 2, 0], dtype=int32)
In [197]: A[idx,:]
Out[197]: 
array([[7, 2, 9],
       [8, 9, 3],
       [5, 7, 8]])
Run Code Online (Sandbox Code Playgroud)

将每行中的元素重新排列为原始对角线并回到对角线上将需要一些实验 - 反复试验。我们可能必须根据与排序相关的某些值“滚动”每一行idx。我不记得是否有一个函数可以单独滚动每一行,或者我们是否必须迭代行才能做到这一点。

In [218]: A1=A[idx,:]
In [219]: [np.roll(a,-i) for a,i in zip(A1,[1,1,1])]
Out[219]: [array([2, 9, 7]), array([9, 3, 8]), array([7, 8, 5])]
In [220]: np.array([np.roll(a,-i) for a,i in zip(A1,[1,1,1])])
Out[220]: 
array([[2, 9, 7],
       [9, 3, 8],
       [7, 8, 5]])
Run Code Online (Sandbox Code Playgroud)

所以滚动就[1,1,1]可以完成这项工作。但我不知道如何得出这一点。我怀疑我们需要生成更多的测试用例,可能是更大的测试用例,并寻找模式。

该滚动可能与该行移动了多少、原始位置和新位置之间的差异有关。咱们试试吧:

np.arange(3)-idx

In [222]: np.array([np.roll(a,i) for a,i in zip(A1,np.arange(3)-idx)])
Out[222]: 
array([[2, 9, 7],
       [9, 3, 8],
       [7, 8, 5]])
Run Code Online (Sandbox Code Playgroud)

将排序应用于idx行和列似乎也能达到目的:

In [227]: A[idx,:][:,idx]
Out[227]: 
array([[2, 9, 7],
       [9, 3, 8],
       [7, 8, 5]])

In [229]: A[idx[:,None],idx]
Out[229]: 
array([[2, 9, 7],
       [9, 3, 8],
       [7, 8, 5]])
Run Code Online (Sandbox Code Playgroud)