我正在将一个MATLAB代码移植到Python的Numpy。
在MATLAB(实际上是Octave)中,我有类似的东西:
>> someArr = [9, 8, 7, 7]
>> [~, ans] = sort(someArr, 'descend')
ans =
1 2 3 4
所以在Numpy,我正在做:
>>> someArr = np.array([9, 8, 7, 7])
>>> np.argsort(someArr)[::-1]
array([0, 1, 3, 2])
我在MATLAB中获得了1, 2, 3, 4
而在Numpy上获得了0, 1, 3, 2
,而我在Numpy上需要0, 1, 2, 3
。
我相信它是由于每个函数中使用的排序算法,但我检查过,看起来两者都使用“quicksort”(请参阅here和here)。
如何将Numpy的解决方案与MATLAB解决方案相匹配?
答案 0 :(得分:4)
为了使这项工作,我们需要有点聪明。 numpy
没有'descend'
类似物。你通过反转排序的结果来模仿它(最终你正在撤消)。
我不确定matlab
如何完成它,但他们声称使用了stable variant of quicksort。具体来说,对于降序排序:
如果标志为'descend',则输出在返回之前反转。在逆转之后,我们运行索引向量排序以恢复稳定性。
octave
似乎在此处效仿。
由于它们的排序是稳定的,因此可以保证输入中的相等值的顺序将保留在输出中。另一方面,numpy
对它的快速排序没有做出这样的保证。如果我们想要一个稳定的numpy排序,我们需要使用mergesort
:
>>> np.argsort(someArr, kind='mergesort')
array([2, 3, 1, 0])
好的,这个输出很有意义。 someArr[2] == someArr[3]
,第三个元素出现在第四个元素之前,因此2
在输出中3
之前是明智的(没有保证稳定的排序算法,我们无法做出此声明) 。现在来了聪明的踩踏......你想要“降序”值,而不是颠倒argsort
的输出,为什么我们不否定输入呢?这将会产生比较低数字排序更大数字排序的效果,正如降序排序那样......
>>> np.argsort(-someArr, kind='quicksort')
array([0, 1, 2, 3])
现在我们正在谈论!由于mergesort保证稳定,因此出现在较低索引处的元素(具有相等的值)将首先出现在输出中 - 就像matlab / octave一样。好的。
答案 1 :(得分:0)
您可以选择不同的排序算法。将其更改为heapsort
对我有用:
>> np.argsort(someArr, kind="heapsort")[::-1]
array([0, 1, 2, 3], dtype=int32)
编辑:这仅适用于我看过的一些测试用例。 [9, 8, 7, 7, 4, 1, 1]
它停止工作。我的回答可能不是一个好的解决方案。
答案 2 :(得分:0)
np.argsort(dataset,axis=-1,kind='stable')