<p dir="auto">After unstacking data that were grouped using groupby the data appears in an unexpected order. The groupby data are in the ascending order, but after unstacking this is no longer true.</p>
<p dir="auto">The following code demonstrates:<br>
import numpy as np<br>
import pandas as pd</p>
<p dir="auto">print pd.<strong>version</strong></p>
<h1 dir="auto">random data</h1>
<p dir="auto">data = pd.DataFrame()<br>
data['a'] = np.random.random(1000)_10. - 2<br>
data['b'] = np.random.random(1000)_10. - 2<br>
data['c'] = np.random.random(1000)*10. - 2</p>
<h1 dir="auto">bins in a and b</h1>
<p dir="auto">ba = np.linspace(-5., 5, 8)<br>
bb = np.linspace(-5., 5, 9)</p>
<h1 dir="auto">groupby bins</h1>
<p dir="auto">groups = data.groupby([pd.cut(data['a'], ba), pd.cut(data['b'], bb)])</p>
<h1 dir="auto">mask, needs at least 10 to get robust std estimate</h1>
<p dir="auto">msk = groups.count()['c'] &gt; 10</p>
<h1 dir="auto">std(c) per bin, these are ordered as expected</h1>
<p dir="auto">stdc = groups['c'].agg([np.std, len])[msk]<br>
print stdc</p>
<h1 dir="auto">now unstack</h1>
<p dir="auto">result = stdc['std'].unstack()</p>
<h1 dir="auto">and the results are not ordered as expected</h1>
<p dir="auto">print result</p>
<p dir="auto">and the result is:<br>
b                 (-1.25, 0]  (-2.5, -1.25]  (0, 1.25]  (1.25, 2.5]  <br>
a<br>
(-0.714, 0.714]     2.878018            NaN   3.019754     2.908735<br>
(-2.143, -0.714]    2.490683            NaN   2.809243     2.754959<br>
(0.714, 2.143]      2.656060       2.940749   2.421975     2.677205<br>
(2.143, 3.571]      3.128538       2.879978   3.038488     3.191041<br>
(3.571, 5]          2.534340       2.943076   3.215626     2.687091</p>
<p dir="auto">b                 (2.5, 3.75]  (3.75, 5]<br>
a<br>
(-0.714, 0.714]      3.328777   3.305938<br>
(-2.143, -0.714]     2.716552   3.090601<br>
(0.714, 2.143]       3.093307   1.669262<br>
(2.143, 3.571]       2.885055   3.295693<br>
(3.571, 5]           3.333355   2.972684</p>
<p dir="auto">[5 rows x 6 columns]</p>
<p dir="auto">This seems to happen if the bins cross zero.</p>
<p dir="auto">I recall discussing this before but came up on the mailing list again. Sorting of cut output is always wrong / ugly. I propose creating a str-like that compares with others of the same type as if they were tuples (possibly with nice logic around ranges) - would be facilitated by intro of CategoricalBlock.</p>
<p dir="auto">Similar to replacing qcut output with this:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def convert_bins_to_tuple(iterable):
    return [(left, right) for elem in iterable for left, right in elem.strip('()[]').split(',')]"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">convert_bins_to_tuple</span>(<span class="pl-s1">iterable</span>):
    <span class="pl-k">return</span> [(<span class="pl-s1">left</span>, <span class="pl-s1">right</span>) <span class="pl-k">for</span> <span class="pl-s1">elem</span> <span class="pl-c1">in</span> <span class="pl-s1">iterable</span> <span class="pl-k">for</span> <span class="pl-s1">left</span>, <span class="pl-s1">right</span> <span class="pl-c1">in</span> <span class="pl-s1">elem</span>.<span class="pl-en">strip</span>(<span class="pl-s">'()[]'</span>).<span class="pl-en">split</span>(<span class="pl-s">','</span>)]</pre></div>