Concatenar columnas de Pandas bajo nuevo nivel de múltiples índices

Dado un diccionario de marcos de datos como:

dict = {'ABC': df1, 'XYZ' : df2} # of any length... 

donde cada dataframe tiene las mismas columnas e índice similar, por ejemplo:

 data Open High Low Close Volume Date 2002-01-17 0.18077 0.18800 0.16993 0.18439 1720833 2002-01-18 0.18439 0.21331 0.18077 0.19523 2027866 2002-01-21 0.19523 0.20970 0.19162 0.20608 771149 

¿Cuál es la forma más sencilla de combinar todos los marcos de datos en uno, con un índice múltiple como:

 symbol ABC XYZ data Open High Low Close Volume Open ... Date 2002-01-17 0.18077 0.18800 0.16993 0.18439 1720833 ... 2002-01-18 0.18439 0.21331 0.18077 0.19523 2027866 ... 2002-01-21 0.19523 0.20970 0.19162 0.20608 771149 ... 

He intentado algunos métodos, por ejemplo, para cada dataframe, reemplace las columnas con un índice múltiple como .from_product(['ABC', columns]) y luego concatene a lo largo del axis=1 , sin éxito.

Puede hacerlo con concat (el argumento de keys creará el índice de columnas jerárquicas):

 d = {'ABC' : df1, 'XYZ' : df2} print pd.concat(d.values(), axis=1, keys=d.keys()) XYZ ABC \ Open High Low Close Volume Open High Date 2002-01-17 0.18077 0.18800 0.16993 0.18439 1720833 0.18077 0.18800 2002-01-18 0.18439 0.21331 0.18077 0.19523 2027866 0.18439 0.21331 2002-01-21 0.19523 0.20970 0.19162 0.20608 771149 0.19523 0.20970 Low Close Volume Date 2002-01-17 0.16993 0.18439 1720833 2002-01-18 0.18077 0.19523 2027866 2002-01-21 0.19162 0.20608 771149 

Realmente concat listas de deseos por lo que lo siguiente es equivalente:

 print(pd.concat([df1, df2], axis=1, keys=['ABC', 'XYZ'])) 

Agregue una columna de símbolos a sus marcos de datos y configure el índice para que incluya la columna de símbolos, concat y luego desapile ese nivel:

Lo siguiente asume que hay tantos símbolos como DataFrames en su dictado, y también que verifica que el orden de los símbolos sea el deseado según el orden de las teclas dict:

 DF_dict = {'ABC': df1, 'XYZ' : df2} dict_keys = DF_dict.keys() symbols = ['ABC', 'ZXY'] for x in xrange(len(symbols)): DF_dict[dict_keys[x]]['symbol'] = symbols[x] DF_dict[dict_keys[x]].reset_index(inplace = True) DF_dict[dict_keys[x]].set_index(['symbol', 'Date'], inplace = True) DF = pd.concat(DF_dict[df] for df in dict_keys) DF = DF.unstack('symbol') 

Creo que ese sería el enfoque que tomaría. Algunas personas están en contra de la syntax inplace . Lo uso aquí solo por conveniencia.