Eu tenho um DataFrame com um MultiIndex criado após alguns agrupamentos:
import numpy as np
import pandas as p
from numpy.random import randn
df = p.DataFrame({
'A' : ['a1', 'a1', 'a2', 'a3']
, 'B' : ['b1', 'b2', 'b3', 'b4']
, 'Vals' : randn(4)
}).groupby(['A', 'B']).sum()
df
Output> Vals
Output> A B
Output> a1 b1 -1.632460
Output> b2 0.596027
Output> a2 b3 -0.619130
Output> a3 b4 -0.002009
Como prefiro um nível ao MultiIndex para transformá-lo em algo como:
Output> Vals
Output> FirstLevel A B
Output> Foo a1 b1 -1.632460
Output> b2 0.596027
Output> a2 b3 -0.619130
Output> a3 b4 -0.002009
axis=1
, uma vez que odf.columns
não tem o método "set_index" como o índice, que sempre me incomoda.pd.Series
objetos, enquanto a resposta atualmente aceita (de 2013) não.FirstLevel
como no['Foo', 'Bar']
primeiro argumento também precisará ter o comprimento correspondente, ou seja[df] * len(['Foo', 'Bar'])
,!pd.concat({'Foo': df}, names=['Firstlevel'])
Você pode primeiro adicioná-lo como uma coluna normal e, em seguida, anexá-lo ao índice atual, para:
E altere o pedido, se necessário:
O que resulta em:
fonte
Acho que esta é uma solução mais geral:
Algumas vantagens sobre as outras respostas:
fonte
Fiz uma pequena função com a resposta dos cxrodgers , que IMHO é a melhor solução, pois funciona puramente em um índice, independente de qualquer quadro de dados ou série.
Há uma correção que adicionei: o
to_frame()
método inventará novos nomes para os níveis de índice que não possuem um. Assim, o novo índice terá nomes que não existem no índice antigo. Eu adicionei algum código para reverter essa mudança de nome.Abaixo está o código, eu mesmo usei por um tempo e parece funcionar bem. Se você encontrar quaisquer problemas ou casos extremos, ficarei muito obrigado a ajustar minha resposta.
Ele passou no seguinte código de teste de unidade:
fonte
Que tal construí-lo do zero com pandas.MultiIndex.from_tuples ?
Da mesma forma que a solução do cxrodger , este é um método flexível e evita modificar o array subjacente para o dataframe.
fonte