How to remove levels from a multi-indexed dataframe?
df.reset_index(level=2, drop=True)
Out[29]:
A
1 1 8
3 9
You don't need to create a new DataFrame instance! You can modify the index:
df.index = df.index.droplevel(2)
df
A
1 1 8
3 9
You can also specify negative indices, for selection from the end:
df.index = df.index.droplevel(-1)
If your index has names like
A
X Y Z
1 1 1 8
3 2 9
Then you can also remove by specifying the index name
df.index = df.index.droplevel(Z)
From 0.24+, we can directly droplevel
on df
. So, to drop the last level of the index:
>>> df
col
1 5 1 4 foo
3 2 8 bar
2 4 3 7 saz
# `axis` defaults to `index` or equivalently 0
>>> df.droplevel(-1, axis="index")
col
1 5 1 foo
3 2 bar
2 4 3 saz
The axis whose levels are dropped can also be controlled with axis
argument and it defaults to 0, i.e., over index. Multiple levels can be dropped at once via supplying a list and if any of the index has a name, those can be used, too (as exemplified in the linked doc).
Note: the argument to droplevel
is tried to be first interpreted as a label; so if any of the levels happens to have an integer name, it will be dropped i.e., not positionally:
>>> df
col
this -1 other 0
1 5 1 4 foo
3 2 8 bar
2 4 3 7 saz
# literally drops `-1` level
>>> df.droplevel(-1)
col
this other 0
1 1 4 foo
2 8 bar
2 3 7 saz
# literally level `0` is dropped
>>> df.droplevel(0)
col
this -1 other
1 5 1 foo
3 2 bar
2 4 3 saz
To make sure a positional dropping happens, we can go for the names
attribute and select positionally there:
>>> df
col
this -1 other 0
1 5 1 4 foo
3 2 8 bar
2 4 3 7 saz
# go get the name of the last level, drop whatever it is
>>> df.droplevel(df.index.names[-1])
col
this -1 other
1 5 1 foo
3 2 bar
2 4 3 saz
# similarly...
>>> df.droplevel(df.index.names[0])
col
-1 other 0
5 1 4 foo
3 2 8 bar
4 3 7 saz
Lastly, droplevel
returns a new dataframe, so df = df.droplevel(...)
is needed to see the change in df
.