首页 文章

基于对角线条目对矩阵进行排序

提问于
浏览
4

首先,我想指出我的问题与此不同:Sort a numpy matrix based on its diagonal

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

A=

5 7 8

7 2 9

8 9 3

我想基于对角线对矩阵进行排序,然后根据它重新排列矩阵元素 . 这就是现在

sorted_A:

2 9 7

9 3 8

7 8 5

注意:

(1) . 对角线已排序

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

到目前为止,我使用蛮力,我提取对角线元素,得到指数O(N²),然后重新排列矩阵(另一个O(N²)) . 我想知道是否有任何有效/优雅的方式来做到这一点 . 我很感激能得到的所有帮助 .

2 回答

  • 1

    基于对角线值对行进行排序很容易:

    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]])
    

    将每行中的元素重新排列到原始对角线后面的对角线将需要进行一些试验 - 试验和错误 . 根据与排序 idx 相关的一些值,我们可能必须'roll' . 我不记得是否有一个函数可以单独滚动每一行,或者我们是否必须遍历行来执行此操作 .

    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]])
    

    所以滚动 [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]])
    

    将排序 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]])
    
  • 2

    在这里,我简化了之前已经陈述过的简单解决方案,但很难让您满意 .

    如果要对表进行排序(例如,混淆矩阵的对角线大小并相应地排列行和列),这将非常有用 .

    >>> A=np.array([[5,1,4],[7,2,9],[8,0,3]])
    >>> A
    array([[5, 1, 4],
       [7, 2, 9],
       [8, 0, 3]])
    >>> diag = np.diag(A)
    >>> diag
    array([5, 2, 3])
    >>> idx=np.argsort(diag) # get the order of items that are in diagon
    >>> A[idx,:][:,idx]  # reorder rows and arrows based on the order of items on diagon
    array([[2, 9, 7],
       [0, 3, 8],
       [1, 4, 5]])
    

    如果你想按降序排序只需添加 idx = idx[::-1] # reverse order

相关问题