Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stack all levels of a MultiIndex

I have a dataframe:

index = pd.MultiIndex.from_product([['a', 'b'], ['A', 'B'], ['One', 'Two']])
df = pd.DataFrame(np.arange(16).reshape(2, 8), columns=index)
df

enter image description here

How do I stack all levels of the MultiIndex without knowing how many levels columns has.

I expect the results to look like this:

0  a  A  One     0
         Two     1
      B  One     2
         Two     3
   b  A  One     4
         Two     5
      B  One     6
         Two     7
1  a  A  One     8
         Two     9
      B  One    10
         Two    11
   b  A  One    12
         Two    13
      B  One    14
         Two    15
dtype: int64
like image 691
piRSquared Avatar asked Jul 11 '16 19:07

piRSquared


2 Answers

You can first find len of levels, get range and pass it to stack:

print (df.columns.nlevels)
3

print (list(range(df.columns.nlevels)))
[0, 1, 2]

print (df.stack(list(range(df.columns.nlevels))))
0  a  A  One     0
         Two     1
      B  One     2
         Two     3
   b  A  One     4
         Two     5
      B  One     6
         Two     7
1  a  A  One     8
         Two     9
      B  One    10
         Two    11
   b  A  One    12
         Two    13
      B  One    14
         Two    15
dtype: int32
like image 50
jezrael Avatar answered Nov 17 '22 16:11

jezrael


If you name the index levels, you can use the list of names, like this:

index = pd.MultiIndex.from_product(
    [['a', 'b'], ['A', 'B'], ['One', 'Two']], 
    names=['idx1', 'idx2', 'idx3']
)
df = pd.DataFrame(np.arange(16).reshape(2, 8), columns=index)
df.stack(index.names)

result:

   idx1  idx2  idx3
0  a     A     One      0
               Two      1
         B     One      2
               Two      3
   b     A     One      4
               Two      5
         B     One      6
               Two      7
1  a     A     One      8
               Two      9
         B     One     10
               Two     11
   b     A     One     12
               Two     13
         B     One     14
               Two     15
dtype: int64
like image 1
Matthias Fripp Avatar answered Nov 17 '22 14:11

Matthias Fripp