2013-06-17 15 views
8

Ho riscontrato il seguente problema di ordinare le intestazioni di riga e colonna.Pandas DataFrame.unstack() Modifica l'ordine delle intestazioni di righe e colonne

Ecco come riprodurre questo:

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()) 

Questo dimostra:

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 

Si noti come le intestazioni non sono più ordinati. Mi chiedo quale sia un buon modo per risolvere questo problema in modo da semplificare il lavoro interattivo.

per tenere traccia più in basso, dove il problema è, eseguire il seguente:

g.unstack().columns 

mi dà questo: Index ([(- 0,567, 0,0321], (0,0321, 0,724], (0.724, 3.478 ], [-2.58, -0,567]], DTYPE = oggetto)

Ora confronta con B.levels:

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

Ovviamente l'ordine originariamente nel Factor si perde

012.351.641.061.745.

Ora per rendere la cosa ancora peggiore, facciamo un tavolo trasversale a più livelli:

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

Essa mostra qualcosa di simile:

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 

sia con la riga e colonna etichette ordinati in modo non corretto.

Grazie.

+2

Questa è una domanda eccellente. La parte strana è che questi oggetti bin sono in realtà solo stringhe. –

risposta

7

Questo mi sembra un po 'di un hack, ma qui va:

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 

avvalendosi del fatto che unique conserva ordine * (afferrando i primi termini unici in dall'indice di g):

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) 

Come potete vedere, questi sono nell'ordine corretto.

Ora è possibile reindex da questo:

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 

che ora è nell'ordine corretto.

Aggiornamento (mi mancava che anche le colonne non fossero in ordine).
È possibile utilizzare lo stesso trucco per le colonne (dovrete catena di queste operazioni):

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

* questo è il motivo per serie unica è significativamente più veloce di np.unique.

+0

Funziona solo sull'intestazione della riga. L'intestazione della colonna ha ancora l'ordine sbagliato. Inoltre, è un po 'noioso scrivere in iPython. C'è un modo più succinto? –

+0

Sì, è decisamente un hack ... (whooops ha presupposto che i cols fossero in ordine, lo stesso hack può essere applicato a loro). Forse qualcun altro avrà un modo migliore! –

+0

Sapete come reindicizzare se l'indice di riga è un MultiIndex? Ho modificato la mia domanda e l'ultima parte mostra la situazione in cui si tratta di un indice a più livelli. Grazie. –

Problemi correlati