Skip to content

Commit

Permalink
Add to_flat_index method to MultiIndex (pandas-dev#22866)
Browse files Browse the repository at this point in the history
  • Loading branch information
WillAyd authored and Pingviinituutti committed Feb 28, 2019
1 parent 21ead56 commit d1c5b7f
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,7 @@ MultiIndex Components
MultiIndex.set_levels
MultiIndex.set_labels
MultiIndex.to_hierarchical
MultiIndex.to_flat_index
MultiIndex.to_frame
MultiIndex.is_lexsorted
MultiIndex.sortlevel
Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.24.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ Other Enhancements
- :func:`~DataFrame.to_parquet` now supports writing a ``DataFrame`` as a directory of parquet files partitioned by a subset of the columns when ``engine = 'pyarrow'`` (:issue:`23283`)
- :meth:`Timestamp.tz_localize`, :meth:`DatetimeIndex.tz_localize`, and :meth:`Series.tz_localize` have gained the ``nonexistent`` argument for alternative handling of nonexistent times. See :ref:`timeseries.timezone_nonexistent` (:issue:`8917`)
- :meth:`read_excel()` now accepts ``usecols`` as a list of column names or callable (:issue:`18273`)
- :meth:`MultiIndex.to_flat_index` has been added to flatten multiple levels into a single-level :class:`Index` object.

.. _whatsnew_0240.api_breaking:

Expand Down
20 changes: 20 additions & 0 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,26 @@ def _format_attrs(self):
"""
return format_object_attrs(self)

def to_flat_index(self):
"""
Identity method.
.. versionadded:: 0.24.0
This is implemented for compatability with subclass implementations
when chaining.
Returns
-------
pd.Index
Caller.
See Also
--------
MultiIndex.to_flat_index : Subclass implementation.
"""
return self

def to_series(self, index=None, name=None):
"""
Create a Series with both index and values equal to the index keys
Expand Down
29 changes: 29 additions & 0 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class MultiIndex(Index):
set_levels
set_labels
to_frame
to_flat_index
is_lexsorted
sortlevel
droplevel
Expand Down Expand Up @@ -1246,6 +1247,34 @@ def to_hierarchical(self, n_repeat, n_shuffle=1):
FutureWarning, stacklevel=2)
return MultiIndex(levels=levels, labels=labels, names=names)

def to_flat_index(self):
"""
Convert a MultiIndex to an Index of Tuples containing the level values.
.. versionadded:: 0.24.0
Returns
-------
pd.Index
Index with the MultiIndex data represented in Tuples.
Notes
-----
This method will simply return the caller if called by anything other
than a MultiIndex.
Examples
--------
>>> index = pd.MultiIndex.from_product(
... [['foo', 'bar'], ['baz', 'qux']],
... names=['a', 'b'])
>>> index.to_flat_index()
Index([('foo', 'baz'), ('foo', 'qux'),
('bar', 'baz'), ('bar', 'qux')],
dtype='object')
"""
return Index(self.values, tupleize_cols=False)

@property
def is_all_dates(self):
return False
Expand Down
8 changes: 8 additions & 0 deletions pandas/tests/indexes/multi/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,11 @@ def test_to_series_with_arguments(idx):
assert s.values is not idx.values
assert s.index is not idx
assert s.name != idx.name


def test_to_flat_index(idx):
expected = pd.Index((('foo', 'one'), ('foo', 'two'), ('bar', 'one'),
('baz', 'two'), ('qux', 'one'), ('qux', 'two')),
tupleize_cols=False)
result = idx.to_flat_index()
tm.assert_index_equal(result, expected)
8 changes: 8 additions & 0 deletions pandas/tests/indexes/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2266,6 +2266,14 @@ def test_tab_complete_warning(self, ip):
with provisionalcompleter('ignore'):
list(ip.Completer.completions('idx.', 4))

def test_to_flat_index(self, indices):
# 22866
if isinstance(indices, MultiIndex):
pytest.skip("Separate expectation for MultiIndex")

result = indices.to_flat_index()
tm.assert_index_equal(result, indices)


class TestMixedIntIndex(Base):
# Mostly the tests from common.py for which the results differ
Expand Down

0 comments on commit d1c5b7f

Please sign in to comment.