# Drop a level from a multi-level column index in Pandas?

## Problem

If I have a multi-level column index, I should:

``````>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> pd.DataFrame([[1,2], [3,4]], columns=cols)
``````
``````    a
---+--
b | c
--+---+--
0 | 1 | 2
1 | 3 | 4
``````

How can I drop the “a” level of that index, so I end up with:

``````    b | c
--+---+--
0 | 1 | 2
1 | 3 | 4
``````

## Solution #1

You can use MultiIndex.droplevel:MultiIndex.droplevel:MultiIndex.droplevel:MultiIndex

``````>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> df = pd.DataFrame([[1,2], [3,4]], columns=cols)
>>> df
a
b  c
0  1  2
1  3  4

[2 rows x 2 columns]
>>> df.columns = df.columns.droplevel()
>>> df
b  c
0  1  2
1  3  4

[2 rows x 2 columns]
``````

## Solution #2

Using a list comprehension is another approach to get rid of the index:

``````df.columns = [col for col in df.columns]

b  c
0  1  2
1  3  4
``````

If you want to merge the names from both levels, as in the example below, where the bottom level contains two ‘y’s, this method is also useful:

``````cols = pd.MultiIndex.from_tuples([("A", "x"), ("A", "y"), ("B", "y")])
df = pd.DataFrame([[1,2, 8 ], [3,4, 9]], columns=cols)

A     B
x  y  y
0  1  2  8
1  3  4  9
``````

When the top level is removed, two columns with the index ‘y’ are left. By connecting the names with the list comprehension, this can be prevented.

``````df.columns = ['_'.join(col) for col in df.columns]

A_x A_y B_y
0   1   2   8
1   3   4   9
``````

That was a difficulty I encountered after doing a groupby, and it took me a long time to figure out what the solution was. I tweaked that solution to fit this particular scenario.

## Solution #3

We may now utilize DataFrame with Pandas 0.24.0. droplevel():

``````cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
df = pd.DataFrame([[1,2], [3,4]], columns=cols)

df.droplevel(0, axis=1)

#   b  c
#0  1  2
#1  3  4
``````

If you want to keep your DataFrame method chain going, this is really beneficial.

## Solution #4

Another option is to use the.xs technique to reassign df based on a cross section of df.

``````>>> df

a
b   c
0   1   2
1   3   4

>>> df = df.xs('a', axis=1, drop_level=True)

# 'a' : key on which to get cross section
# axis=1 : get cross section of column
# drop_level=True : returns cross section without the multilevel index

>>> df

b   c
0   1   2
1   3   4
``````