Skip to content

Index.droplevel when names are tuples #21120

Open
@toobaz

Description

@toobaz

Code Sample, a copy-pastable example if possible

In [2]: mi = pd.MultiIndex.from_product([[0, 1]]*2, names=[('first', 'level'), ('second', 'level')])

In [3]: mi.droplevel(('first', 'level'))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/nobackup/repo/pandas/pandas/core/indexes/multi.py in _get_level_number(self, level)
    775                                  'level number' % level)
--> 776             level = self.names.index(level)
    777         except ValueError:

ValueError: 'first' is not in list

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-3-1952401ac0fc> in <module>()
----> 1 mi.droplevel(('first', 'level'))

~/nobackup/repo/pandas/pandas/core/indexes/base.py in droplevel(self, level)
   3177             level = [level]
   3178 
-> 3179         levnums = sorted(self._get_level_number(lev) for lev in level)[::-1]
   3180 
   3181         if len(level) == 0:

~/nobackup/repo/pandas/pandas/core/indexes/base.py in <genexpr>(.0)
   3177             level = [level]
   3178 
-> 3179         levnums = sorted(self._get_level_number(lev) for lev in level)[::-1]
   3180 
   3181         if len(level) == 0:

~/nobackup/repo/pandas/pandas/core/indexes/multi.py in _get_level_number(self, level)
    777         except ValueError:
    778             if not isinstance(level, int):
--> 779                 raise KeyError('Level %s not found' % str(level))
    780             elif level < 0:
    781                 level += self.nlevels

KeyError: 'Level first not found'

In [4]: mi.droplevel([('first', 'level')])
Out[4]: Int64Index([0, 1, 0, 1], dtype='int64', name=('second', 'level'))

Problem description

Always the same story: if we allow users to pass tuples of stuff interchangeably with lists of stuff, then tuples as values (or names, as in this case) will cause problems.

Expected Output

Out[4]

... as long as we all agree that the level argument can accept lists of names but not tuples of names. The only other option I see is to document that droplevel does not support tuple names (except as items of a list).

Output of pd.show_versions()

INSTALLED VERSIONS

commit: None
python: 3.5.3.final.0
python-bits: 64
OS: Linux
OS-release: 4.9.0-6-amd64
machine: x86_64
processor:
byteorder: little
LC_ALL: None
LANG: it_IT.UTF-8
LOCALE: it_IT.UTF-8

pandas: 0.24.0.dev0+14.g489cc24c8.dirty
pytest: 3.5.0
pip: 9.0.1
setuptools: 39.0.1
Cython: 0.25.2
numpy: 1.14.1
scipy: 0.19.0
pyarrow: None
xarray: None
IPython: 6.2.1
sphinx: 1.5.6
patsy: 0.5.0
dateutil: 2.7.0
pytz: 2017.2
blosc: None
bottleneck: 1.2.0dev
tables: 3.3.0
numexpr: 2.6.1
feather: 0.3.1
matplotlib: 2.0.0
openpyxl: 2.3.0
xlrd: 1.0.0
xlwt: 1.3.0
xlsxwriter: 0.9.6
lxml: 4.1.1
bs4: 4.5.3
html5lib: 0.999999999
sqlalchemy: 1.0.15
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: 0.2.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugMultiIndexNested DataData where the values are collections (lists, sets, dicts, objects, etc.).

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions