2013-06-17 7 views
8

Ich habe das folgende Problem beim Sortieren der Zeilen- und Spaltenüberschriften festgestellt.Pandas DataFrame.unstack() ändert die Reihenfolge der Zeilen- und Spaltenüberschriften

Hier ist, wie diese zu reproduzieren:

X =pd.DataFrame(dict(x=np.random.normal(size=100), y=np.random.normal(size=100))) 
A=pd.qcut(X['x'], [0,0.25,0.5,0.75,1.0]) #create a factor 
B=pd.qcut(X['y'], [0,0.25,0.5,0.75,1.0]) # create another factor 

g = X.groupby([A,B])['x'].mean() #do a two-way bucketing 


print g 

#this gives the following and so far so good 

x     y    
[-2.315, -0.843] [-2.58, -0.567] -1.041167 
        (-0.567, 0.0321] -1.722926 
        (0.0321, 0.724] -1.245856 
        (0.724, 3.478]  -1.240876 
(-0.843, -0.228] [-2.58, -0.567] -0.576264 
        (-0.567, 0.0321] -0.501709 
        (0.0321, 0.724] -0.522697 
        (0.724, 3.478]  -0.506259 
(-0.228, 0.382] [-2.58, -0.567]  0.175768 
        (-0.567, 0.0321] 0.214353 
        (0.0321, 0.724]  0.113650 
        (0.724, 3.478]  -0.013758 
(0.382, 2.662] [-2.58, -0.567]  0.983807 
        (-0.567, 0.0321] 1.214640 
        (0.0321, 0.724]  0.808608 
        (0.724, 3.478]  1.515334 
Name: x, dtype: float64 

#Now let's make a two way table and here is the problem: 

HTML(g.unstack().to_html()) 

Dies zeigt:

y     (-0.567, 0.0321] (0.0321, 0.724] (0.724, 3.478] [-2.58, -0.567] 
x                     
(-0.228, 0.382]   0.214353   0.113650  -0.013758   0.175768 
(-0.843, -0.228]   -0.501709  -0.522697  -0.506259  -0.576264 
(0.382, 2.662]   1.214640   0.808608  1.515334   0.983807 
[-2.315, -0.843]   -1.722926  -1.245856  -1.240876  -1.041167 

Hinweis, wie die Header werden nicht mehr sortiert. Ich frage mich, was ist ein guter Weg, um dieses Problem zu lösen, um interaktive Arbeit einfach zu machen.

weiter auf der Spur, wo das Problem ist, das folgend laufen:

g.unstack().columns 

Es gibt mir diese: Index ([(- 0,567, 0,0321], (0,0321, 0,724], (0,724, 3,478 ], [-2,58, -0,567]], dtype = Objekt)

Nun ist diese vergleichen mit B.levels:

B.levels 
Index([[-2.58, -0.567], (-0.567, 0.0321], (0.0321, 0.724], (0.724, 3.478]], dtype=object) 

Offensichtlich ist die Reihenfolge, in Factor ursprünglich verloren

.

Nun ist die Sache noch schlimmer zu machen, lassen Sie uns einen Multi-Level-Kreuztisch tun:

g2 = X.groupby([A,B]).agg('mean') 
g3 = g2.stack().unstack(-2) 
HTML(g3.to_html()) 

Es zeigt so etwas wie:

y     (-0.567, 0.0321] (0.0321, 0.724] (0.724, 3.478] 
x                  
(-0.228, 0.382] x   0.214353   0.113650  -0.013758 
       y   -0.293465   0.321836  1.180369 
(-0.843, -0.228] x   -0.501709  -0.522697  -0.506259 
       y   -0.204811   0.324571  1.167005 
(0.382, 2.662] x   1.214640   0.808608  1.515334 
       y   -0.195446   0.161198  1.074532 
[-2.315, -0.843] x   -1.722926  -1.245856  -1.240876 
       y   -0.392896   0.335471  1.730513 

sowohl mit der Zeilen- und Spaltenbeschriftungen falsch sortiert.

Danke.

+2

Dies ist eine ausgezeichnete Frage. Der seltsame Teil ist, dass diese Bin-Objekte eigentlich nur Strings sind. –

Antwort

7

Dies scheint ein bisschen ein Hack, aber hier geht:

In [11]: g_unstacked = g.unstack() 

In [12]: g_unstacked 
Out[12]: 
y     (-0.565, 0.12] (0.12, 0.791] (0.791, 2.57] [-2.177, -0.565] 
x 
(-0.068, 0.625]   0.389408  0.267252  0.283344   0.258337 
(-0.892, -0.068]  -0.121413  -0.471889  -0.448977   -0.462180 
(0.625, 1.639]   0.987372  1.006496  0.830710   1.202158 
[-3.124, -0.892]  -1.513954  -1.482813  -1.394198   -1.756679 

die Tatsache Gebrauch macht, daß unique Auftrag * bewahrt (aus dem Index von g den einzigartigen ersten Terme in Rupfen):

In [13]: g.index.get_level_values(0).unique() 
Out[13]: 
array(['[-3.124, -0.892]', '(-0.892, -0.068]', '(-0.068, 0.625]', 
     '(0.625, 1.639]'], dtype=object) 

Wie Sie sehen können, sind diese in der richtigen Reihenfolge.

Jetzt können Sie reindex durch das:

In [14]: g_unstacked.reindex(g.index.get_level_values(0).unique()) 
Out[14]: 
y     (-0.565, 0.12] (0.12, 0.791] (0.791, 2.57] [-2.177, -0.565] 
[-3.124, -0.892]  -1.513954  -1.482813  -1.394198   -1.756679 
(-0.892, -0.068]  -0.121413  -0.471889  -0.448977   -0.462180 
(-0.068, 0.625]   0.389408  0.267252  0.283344   0.258337 
(0.625, 1.639]   0.987372  1.006496  0.830710   1.202158 

die jetzt in der richtigen Reihenfolge ist.

Update (Ich verpasste, dass die Spalten auch nicht in Ordnung waren).
Sie können den gleichen Trick für die Spalten verwenden (Sie diese Operationen Kette haben werden):

In [15]: g_unstacked.reindex_axis(g.index.get_level_values(1).unique(), axis=1) 

* dies ist der Grund Series als np.unique deutlich schneller einzigartig ist.

+0

Dies funktioniert nur auf den Zeilenkopf. Der Spaltentitel hat immer noch die falsche Reihenfolge. Es ist auch etwas mühsam, iPython einzugeben. Gibt es einen prägnanteren Weg? –

+0

Yup, es ist definitiv ein Hack ... (Whoooops angenommen, die Spalten waren in Ordnung, der gleiche Hack kann auf sie angewendet werden). Vielleicht hat jemand anderes einen besseren Weg! –

+0

Können Sie neu indizieren, wenn der Zeilenindex ein MultiIndex ist? Ich habe meine Frage bearbeitet und der letzte Teil zeigt die Situation, in der es sich um einen mehrstufigen Index handelt. Vielen Dank. –

Verwandte Themen