47

I have a multi level column table like this:

    a
   ---+---+---
    b | c | f
--+---+---+---
0 | 1 | 2 | 7
1 | 3 | 4 | 9

How can I drop column "c" by name? to look like this:

    a
   ---+---
    b | f
--+---+---
0 | 1 | 7
1 | 3 | 9

I tried this:

del df['c']

but I get the following error, which makes sense:

KeyError: 'Key length (1) was greater than MultiIndex lexsort depth (0)'

3 Answers 3

61

With a multi-index we have to specify the column using a tuple in order to drop a specific column, or specify the level to drop all columns with that key on that index level.

Instead of saying drop column 'c' say drop ('a','c') as shown below:

df.drop(('a', 'c'), axis = 1, inplace = True)

Or specify the level as shown below

df.drop('c', axis = 1, level = 1)

Let's make a simple df to demonstrate on:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c"),
...                                   ("a", "f"), ('x', 'c'),('x', 'f')])
>>> df = pd.DataFrame([[1,3, 7, 21, 8], [2, 4, 9, 21, 8]], columns=cols)
>>> df
   a         x   
   b  c  f   c  f
0  1  3  7  21  8
1  2  4  9  21  8

Now here's how to drop 'c' from 'a'

>>> df.drop(('a', 'c'), axis = 1)
   a      x   
   b  f   c  f
0  1  7  21  8
1  2  9  21  8

With a three level index then include that key in the tuple to drop from the bottom level e.g. ('a','c','k')

With a single value as the index, like you did, it searches the top level index for a match by default and drops a match on that index or throws an error if the key is not in the index, like you found.

So in my example it would be fine to tell it to drop just 'x'

>>> df.drop('x', axis = 1)
   a      
   b  c  f
0  1  3  7
1  2  4  9

To drop all columns with the second index 'c', then specify the level

>>> df.drop('c', axis = 1, level = 1)
   a     x
   b  f  f
0  1  7  8
1  2  9  8
Sign up to request clarification or add additional context in comments.

Comments

49

Solved:

df.drop('c', axis=1, level=1)

5 Comments

Even though the DataFrame does not seem to contain the c column anymore, when I query df.columns the deleted columns indexes show up.
I have the same problem, did you find any solution?
I think I found the culprit. The levels are a FrozenList and therefore not touched by this operation. You can get the up to date index by using df.columns.remove_unused_levels().
Tnx, @KevinWittek. Here is a snippet to show how it works:cols = pd.MultiIndex.from_tuples( [("a", "b"), ("a", "c"), ("a", "f"), ("x", "c"), ("x", "f")] ) df = pd.DataFrame([[1, 3, 7, 21, 8], [2, 4, 9, 21, 8]], columns=cols) df.drop(["x"], inplace=True, axis=1, level=0) df.columns.remove_unused_levels().levels[0]
You should use inplace = True, but it looks like that in general pandas if getting rid of the inplace option, so perhaps it is better to do df = df.drop('c', axis=1, level=1).
-1

This doen't work for me. It works when 'inplace=True' is added. The correct statement is df.drop('c', axis = 1, level = 1, inplace=True)

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.