在Python中排序数组而不修改特定的元素位置

时间:2015-03-02 14:13:05

标签: python sorting numpy

我在Python中有一个numpy数组,它是n-by-n(在这个例子中是3-by-3)并且在所有对角线位置都包含零值。 e.g

array([[ 0.   , -0.65  ,  1.3 ,   0.56],
       [ 0.45 ,  0.    ,  0.54,   43   ],
       [ 0.5  ,  0.12  ,  0.  ,   7    ]
       [ 0.2  ,  0.3  ,  0.4  ,   0    ]])

是否可以在不修改对角线位置的情况下对数组进行排序,使其看起来像下面那样?因为所有的排序功能都会考虑到"零"存在于对角线位置并将改变它们的相对位置。

array([[ 0.   , 1.3    ,  0.56  ,   -0.65],
       [ 43   ,  0.    ,  0.54  ,   0.45   ],
       [ 7    ,  0.5   ,  0.    ,   0.12    ]
       [ 0.4  ,  0.3  ,  0.2    ,   0    ]])

如果无法完成上述操作,那么每行中的N个最大值及其对应的索引就足够了。

直到现在我已经尝试过sort和argsort但没有结果。

2 个答案:

答案 0 :(得分:2)

我对这个问题迟到了,但如果你正在寻找一个仅限NumPy的解决方案,你可以用inf替换你的对角线,按照你选择的顺序排序,然后随机播放inf列回到对角线:

In [189]: a = np.array([[ 0.   , -0.65  ,  1.3 ,   0.56],
   .....:        [ 0.45 ,  0.    ,  0.54,   43   ],
   .....:        [ 0.5  ,  0.12  ,  0.  ,   7    ],
   .....:        [ 0.2  ,  0.3  ,  0.4  ,   0    ]])

In [190]: np.fill_diagonal(a,np.inf)

In [191]: a.sort()

In [192]: a = a[:,::-1]

In [193]: for i in range(1,len(a)):
   .....:         a[i,:i+1] = np.roll(a[i,:i+1], i)
   .....:     

In [194]: np.fill_diagonal(a, 0)

In [195]: a
Out[195]: 
array([[  0.  ,   1.3 ,   0.56,  -0.65],
   [ 43.  ,   0.  ,   0.54,   0.45],
   [  7.  ,   0.5 ,   0.  ,   0.12],
   [  0.4 ,   0.3 ,   0.2 ,   0.  ]])

答案 1 :(得分:1)

最简单的方法是删除零,排序,然后沿对角线添加零:

>>> a = [[0,1,2],[3,0,0],[5,6,0]]
>>> no_zeroes = [r[:i] + r[i+1:] for i, r in enumerate(a)]
>>> no_zeroes
[[1, 2], [3, 0], [5, 6]]
>>> sorted_no_zeroes = [sorted(r, reverse=True) for r in no_zeroes]
>>> sorted_no_zeroes
[[2, 1], [3, 0], [6, 5]]
>>> sorted_with_zeroes = [r[:i] + [0] + r[i:] for i, r in enumerate(sorted_no_zeroes)]
>>> sorted_with_zeroes
[[0, 2, 1], [3, 0, 0], [6, 5, 0]]

包装成一个功能:

>>> def sort_ignoring_zeroes(a):
...  s = [sorted(r[:i] + r[i+1:], reverse=True) for i, r in enumerate(a)]
...  return [r[:i] + [0] + r[i:] for i, r in enumerate(s)]
...
>>> sort_ignoring_zeroes(
          [[ 0.   , 1.3    ,  0.56  ,   -0.65],
...        [ 43   ,  0.    ,  0.54  ,   0.45],
...        [ 7    ,  0.5   ,  0.    ,   0.12]])
[[0, 1.3, 0.56, -0.65],
 [43, 0, 0.54, 0.45],
 [7, 0.5, 0, 0.12]]
>>>