title: Pandas sorting by value and then by index
body: <p>I have the following dataset:</p>
  
  <pre><code>import numpy as np
  from pandas import DataFrame
  import numpy.random as random
  
  random.seed(12)
  
  df = DataFrame (
      {
          "fac1" : ["a","a","a","a","b","b","b","b"] ,
          "val" : random.choice(np.arange(0,20), 8, replace=False)
      }
  )
  df2 = df.set_index(["fac1"])
  df2
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/IqULV.png" rel="noreferrer"><img src="https://i.stack.imgur.com/IqULV.png" alt="enter image description here"></a></p>
  
  <p>What I want is to sort by <code>val</code> within each <code>fac1</code> group, to produce this:</p>
  
  <p><a href="https://i.stack.imgur.com/PcYGc.png" rel="noreferrer"><img src="https://i.stack.imgur.com/PcYGc.png" alt="enter image description here"></a></p>
  
  <p>I have combed the documentation and cannot find a straightforward way.  The best I could do was the following hack:</p>
  
  <pre><code>df3 = df2.reset_index()
  df4 = df3.sort_values(["fac1","val"],ascending=[True,True],axis=0)
  df5 = df4.set_index(["fac1"])
  df5
  # Produces the picture above
  </code></pre>
  
  <p>(I realize the above could benefit from multiple <code>inplace</code> options, just doing it this way to make intermediate products clear).</p>
  
  <p>I did find <a href="https://stackoverflow.com/questions/33190633/python-pandas-sorting-by-multiindex-and-column">this SO post</a>, which uses grouping and a sorting function.  However the following code, adapted from that post, produced an incorrect result:</p>
  
  <pre><code>df2.groupby("fac1",axis=1).apply(lambda x : x.sort_values("val"))
  </code></pre>
  
  <p>(Output removed for space considerations)</p>
  
  <p>Is there another way to approach this?</p>
  
  <h2>Update: Solution</h2>
  
  <p>The accepted solution is:</p>
  
  <pre><code>df2.sort_values(by='val').sort_index(kind='mergesort')
  </code></pre>
  
  <p>The sorting algorithm <strong>must be <code>mergesort</code></strong> and it must be explicitly specified as it is not the default.  As <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sort_index.html" rel="noreferrer">the <code>sort_index</code> documentation</a> points out, "mergesort is the only <a href="https://en.wikipedia.org/wiki/Sorting_algorithm#Stability" rel="noreferrer">stable</a> algorithm." Here's another sample dataset that will not sort properly if you don't specify <code>mergesort</code> for <code>kind</code>:</p>
  
  <pre><code>random.seed(12)
  
  len = 32 
  
  df = DataFrame (
      {
          "fac1" : ["a" for i in range(int(len/2))] + ["b" for i in range(int(len/2))] ,
          "val" : random.choice(np.arange(0,100), len, replace=False)
      }
  )
  df2 = df.set_index(["fac1"])
  df2.sort_values(by='val').sort_index()
  </code></pre>
  
  <p>(Am omitting all outputs for space consideration)</p>