Skip to content

API: harmonize Index.to_flat_index to MultiIndex.to_flat_index #25094

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.24.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Bug Fixes

**Indexing**

-
- :meth:`Index.to_flat_index` now always returns an :class:`Index` containing tuples, even in the case the original object was already a flat :class:`Index` (:issue:`23670`).
-
-

Expand Down
24 changes: 16 additions & 8 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1105,23 +1105,31 @@ def summary(self, name=None):

def to_flat_index(self):
"""
Identity method.
Convert a MultiIndex to an Index of Tuples containing the level values.
.. versionadded:: 0.24.0
This is implemented for compatability with subclass implementations
when chaining.
Returns
-------
pd.Index
Caller.
Index with the MultiIndex data represented in Tuples.
See Also
Examples
--------
MultiIndex.to_flat_index : Subclass implementation.
>>> 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 self

from .multi import MultiIndex
if not isinstance(self, MultiIndex):
self = MultiIndex.from_product([self])

return Index(self.values, tupleize_cols=False)

def to_series(self, index=None, name=None):
"""
Expand Down
29 changes: 0 additions & 29 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ class MultiIndex(Index):
set_levels
set_codes
to_frame
to_flat_index
is_lexsorted
sortlevel
droplevel
Expand Down Expand Up @@ -1523,34 +1522,6 @@ def to_hierarchical(self, n_repeat, n_shuffle=1):
FutureWarning, stacklevel=2)
return MultiIndex(levels=levels, codes=codes, 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: 0 additions & 8 deletions pandas/tests/indexes/multi/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,3 @@ 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)
13 changes: 9 additions & 4 deletions pandas/tests/indexes/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,17 @@ def test_corner_union(self, indices, fname, sname, expected_name):
tm.assert_index_equal(union, expected)

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

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

if isinstance(indices, MultiIndex):
values = [tuple(v) for v in indices]
else:
values = [(v,) for v in indices]
expected = pd.Index(values, tupleize_cols=False)

tm.assert_index_equal(result, expected)

def test_wrong_number_names(self, indices):
with pytest.raises(ValueError, match="^Length"):
Expand Down