MATLAB sort() vs Numpy argsort() - how to match results?
<p>I'm porting a MATLAB code to Python's Numpy.</p>

<p>In MATLAB (Octave, actually), I have something like:</p>

<pre><code>&gt;&gt; someArr = [9, 8, 7, 7]
&gt;&gt; [~, ans] = sort(someArr, 'descend')
   ans =
   1   2   3   4
</code></pre>

<p>So in Numpy I'm doing:</p>

<pre><code>&gt;&gt;&gt; someArr = np.array([9, 8, 7, 7])
&gt;&gt;&gt; np.argsort(someArr)[::-1]
array([0, 1, 3, 2])
</code></pre>

<p>I got <code>1, 2, 3, 4</code> in MATLAB while <code>0, 1, 3, 2</code> on Numpy, and I need <code>0, 1, 2, 3</code> on Numpy.  </p>

<p>I believe it due to the sorting algorithm used in each function, But I checked and it looks like both are using "quicksort" (see <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html" rel="nofollow">here</a> and <a href="https://www.mathworks.com/matlabcentral/answers/96656-what-type-of-sort-does-the-sort-function-in-matlab-perform" rel="nofollow">here</a>). </p>

<p>How can I match the Numpy's solution to the MATLAB one?</p>

<p>In order to make this work, we need to be a little bit clever.  <code>numpy</code> doesn't have the <code>'descend'</code> analog.  You're mimicking it by reversing the results of the sort (which is ultimately you're undoing).</p>

<p>I'm not sure how <code>matlab</code> accomplishes it, but they claim to use a <a href="http://www.mathworks.com/company/newsletters/articles/an-adventure-of-sortsbehind-the-scenes-of-a-matlab-upgrade.html" rel="nofollow">stable variant of quicksort</a>.  Specifically, for descending sorts:</p>

<blockquote>
  <p>If the flag is 'descend', the output is reversed just before being returned. After the reversal, we ran the index vector sorts to restore stability.</p>
</blockquote>

<p>It appears that <code>octave</code> follows suit here.</p>

<p>Since their sort is stable, you have the guarantee that the order of equal values in the input will be preserved in the output.  <code>numpy</code> on the other hand makes no such guarantees for it's quicksort.  If we want a stable sort in numpy, we need to use <code>mergesort</code>:</p>

<pre><code>&gt;&gt;&gt; np.argsort(someArr, kind='mergesort')
array([2, 3, 1, 0])
</code></pre>

<p>Ok, this output makes sense.  <code>someArr[2] == someArr[3]</code> and the third element comes before the fourth so it is sensible that <code>2</code> would be before <code>3</code> in the output (without a guaranteed stable sorting algorithm, we couldn't make this claim).  Now comes the clever stepping... You want the "descending" values, but rather than reversing the output of <code>argsort</code>, why don't we negate the input?  That will have the effect of larger numbers sorting before than their lower counterparts just as a descending sort would do...</p>

<pre><code>&gt;&gt;&gt; np.argsort(-someArr, kind='quicksort')
array([0, 1, 2, 3])
</code></pre>

<p>Now we're talkin!  And since mergesort is guaranteed to be stable, elements (with equal values) which appear at lower indices will appear in the output first -- Just like matlab/octave.  Nice.</p>

python matlab sorting numpy