2012-06-25 1 views
11

Ho un indice multi-indicizzato DataFrame con nomi associati ai livelli di colonna. Mi piacerebbe essere in grado di mischiare facilmente le colonne in modo che corrispondano all'ordine specificato dall'utente. Dal momento che questo non è disponibile, non sono in grado di utilizzare this recommended solution e ordinarli correttamente al momento della creazione.Come riordinare le colonne di dataframe con più indici a un livello specifico

Ho una tabella di dati che sembra (qualcosa) come

Experiment   BASE   IWWGCW   IWWGDW 
Lead Time    24  48  24  48  24  48 
2010-11-27 12:00:00 0.997 0.991 0.998 0.990 0.998 0.990 
2010-11-28 12:00:00 0.998 0.987 0.997 0.990 0.997 0.990 
2010-11-29 12:00:00 0.997 0.992 0.997 0.992 0.997 0.992 
2010-11-30 12:00:00 0.997 0.987 0.997 0.987 0.997 0.987 
2010-12-01 12:00:00 0.996 0.986 0.996 0.986 0.996 0.986 

voglio prendere in una lista come ['IWWGCW', 'IWWGDW', 'BASE'] e riordinare questo essere:

Experiment   IWWGCW   IWWGDW   BASE   
Lead Time    24  48  24  48  24  48 
2010-11-27 12:00:00 0.998 0.990 0.998 0.990 0.997 0.991 
2010-11-28 12:00:00 0.997 0.990 0.997 0.990 0.998 0.987 
2010-11-29 12:00:00 0.997 0.992 0.997 0.992 0.997 0.992 
2010-11-30 12:00:00 0.997 0.987 0.997 0.987 0.997 0.987 
2010-12-01 12:00:00 0.996 0.986 0.996 0.986 0.996 0.986 

con l'avvertenza che io don sapere sempre a quale livello "Experiment" sarà. Ho provato (dove df è la struttura multi-indicizzato mostrato sopra)

df2 = df.reindex_axis(['IWWGCW', 'IWWGDW', 'BASE'], axis=1, level='Experiment') 

ma che non sembrano funzionare - è completato con successo, ma il dataframe che è stato restituito avuto il suo ordine della colonna invariata.

mia soluzione è quella di avere una funzione come:

def reorder_columns(frame, column_name, new_order): 
    """Shuffle the specified columns of the frame to match new_order.""" 

    index_level = frame.columns.names.index(column_name) 
    new_position = lambda t: new_order.index(t[index_level]) 
    new_index = sorted(frame.columns, key=new_position) 
    new_frame = frame.reindex_axis(new_index, axis=1) 
    return new_frame 

dove reorder_columns(df, 'Experiment', ['IWWGCW', 'IWWGDW', 'BASE']) fa quello che mi aspetto, ma ci si sente come sto facendo un lavoro extra. C'è un modo più semplice per farlo?

risposta

4

Non conosco nulla di fuori mano. Creato un biglietto miglioramento su di esso:

http://github.com/pydata/pandas/issues/1864

+3

Sembra che questa ha è stato risolto con https://github.com/pydata/pandas/issues/4088 – MERose

+0

Questa è la sintassi: 'df.reindex (['top', 'mid', 'btm'], level = 'first')' https://github.com/pandas-dev/pandas/pull/9019 –

7

C'è un modo molto semplice: basta creare un nuovo dataframe basato sull'originale, con il corretto ordine di colonne multiindex:

multi_tuples = [('IWWGCW',24), ('IWWGCW',48), ('IWWGDW',24), ('IWWGDW',48) 
    , ('BASE',24), ('BASE',48)] 

multi_cols = pd.MultiIndex.from_tuples(multi_tuples, names=['Experiment', 'Lead Time']) 

df_ordered_multi_cols = pd.DataFrame(df_ori, columns=multi_cols) 
+0

Questa è la risposta corretta. – mrp