2012-06-25 13 views
11

Tengo un DataFrame multi-indexado con los nombres asociados a los niveles de columna. Me gustaría poder barajar fácilmente las columnas para que coincidan con el orden especificado por el usuario. Como esto ya no existe, no puedo usar this recommended solution y ordenarlos correctamente en el momento de la creación.¿Cómo puedo reordenar columnas de cuadros múltiples de datos en un nivel específico?

que tienen una tabla de datos que se ve (algo) como

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 

quiero tomar en una lista como ['IWWGCW', 'IWWGDW', 'BASE'] y reordenar este ser:

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 la advertencia de que Don 't siempre sé a qué nivel será "Experimento". Probé (donde df es el marco de múltiples indexada se muestra arriba)

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

pero que no parecen funcionar - es completado con éxito, pero la trama de datos que fue devuelto tenido su orden de las columnas sin cambios.

Mi solución es tener una función como:

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 

donde reorder_columns(df, 'Experiment', ['IWWGCW', 'IWWGDW', 'BASE']) hace lo que yo esperaba pero se siente como que estoy haciendo un trabajo extra. ¿Hay alguna forma más fácil de hacer esto?

Respuesta

4

No tengo conocimiento de nada. Creado un billete de mejora al respecto:

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

+3

Parece que esto tiene ha sido resuelto con https://github.com/pydata/pandas/issues/4088 – MERose

+0

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

7

Hay una forma muy sencilla: basta con crear una nueva trama de datos basado en el original, con el orden correcto de columnas 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

Esta es la respuesta correcta. – mrp

Cuestiones relacionadas