Skip to content

Commit 3dc0056

Browse files
committed
introspect results from map so that if the output array has tuples we create a multiindex instead of an index
1 parent 8435c1d commit 3dc0056

File tree

6 files changed

+41
-31
lines changed

6 files changed

+41
-31
lines changed

doc/source/whatsnew/v0.19.1.txt

-22
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,7 @@ Performance Improvements
2626
- Improved performance in ``DataFrame.asof(where)`` when ``where`` is a scalar (:issue:`14461)
2727

2828

29-
.. _whatsnew_0191.api:
3029

31-
API changes
32-
~~~~~~~~~~~
33-
34-
- ``map`` on an ``Index`` now returns an ``Index``, not an array (:issue:`12766`)
35-
.. ipython:: python
36-
37-
idx = Index([1, 2])
38-
idx
39-
40-
Previous Behavior:
41-
42-
.. code-block:: ipython
43-
44-
In [3]: idx.map(lambda x: x * 2)
45-
Out[3]: array([2, 4])
46-
47-
New Behavior:
48-
49-
.. ipython:: python
50-
51-
idx.map(lambda x: x * 2)
5230

5331
.. _whatsnew_0191.bug_fixes:
5432

doc/source/whatsnew/v0.20.0.txt

+19
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,25 @@ Other enhancements
3838
Backwards incompatible API changes
3939
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4040

41+
- ``map`` on an ``Index`` now returns an ``Index``, not an array (:issue:`12766`)
42+
.. ipython:: python
43+
44+
idx = Index([1, 2])
45+
idx
46+
47+
Previous Behavior:
48+
49+
.. code-block:: ipython
50+
51+
In [3]: idx.map(lambda x: x * 2)
52+
Out[3]: array([2, 4])
53+
54+
New Behavior:
55+
56+
.. ipython:: python
57+
58+
idx.map(lambda x: x * 2)
59+
4160
.. _whatsnew_0200.api:
4261

4362

pandas/indexes/base.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -2438,10 +2438,17 @@ def map(self, mapper):
24382438
-------
24392439
applied : Index
24402440
The output of the mapping function applied to the index.
2441+
If the function returns a tuple a
24412442
"""
2443+
from .multi import MultiIndex
2444+
mapped_values = self._arrmap(self.values, mapper)
24422445
attributes = self._get_attributes_dict()
2446+
if mapped_values.size and isinstance(mapped_values[0], tuple):
2447+
return MultiIndex.from_tuples(mapped_values,
2448+
names=attributes.get('name'))
2449+
24432450
attributes['copy'] = False
2444-
return Index(self._arrmap(self.values, mapper), **attributes)
2451+
return Index(mapped_values, **attributes)
24452452

24462453
def isin(self, values, level=None):
24472454
"""

pandas/tests/indexes/test_base.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -767,20 +767,24 @@ def test_sub(self):
767767
self.assertRaises(TypeError, lambda: idx.tolist() - idx)
768768

769769
def test_map_identity_mapping(self):
770+
# GH 12766
770771
for name, cur_index in self.indices.items():
771-
if name == 'tuples':
772-
expected = Index(cur_index.values, tupleize_cols=False)
773-
self.assert_index_equal(expected, cur_index.map(lambda x: x))
774-
else:
775-
self.assert_index_equal(cur_index, cur_index.map(lambda x: x))
772+
self.assert_index_equal(cur_index, cur_index.map(lambda x: x))
776773

777-
def test_map_that_returns_tuples_creates_index_not_multi_index(self):
774+
def test_map_that_returns_tuples_creates_multi_index(self):
775+
# GH 12766
778776
boolean_index = tm.makeIntIndex(3).map(lambda x: (x, x == 1))
779-
expected = Index([(0, False), (1, True), (2, False)],
780-
tupleize_cols=False)
777+
expected = MultiIndex.from_tuples([(0, False), (1, True), (2, False)])
778+
self.assert_index_equal(boolean_index, expected)
779+
780+
def test_map_that_returns_a_length_one_tuple_creates_an_index(self):
781+
# GH 12766
782+
boolean_index = tm.makeIntIndex(3).map(lambda x: (x, ))
783+
expected = Index([(0, ), (1, ), (2, )])
781784
self.assert_index_equal(boolean_index, expected)
782785

783786
def test_map_that_reduces_multi_index_to_single_index_returns_index(self):
787+
# GH 12766
784788
first_level = ['foo', 'bar', 'baz']
785789
multi_index = MultiIndex.from_tuples(lzip(first_level, [1, 2, 3]))
786790
reduced_index = multi_index.map(lambda x: x[0])

pandas/tests/indexes/test_category.py

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ def test_map(self):
218218
ordered=False, name='XXX')
219219
tm.assert_index_equal(result, exp)
220220

221+
# GH 12766: Return an index not an array
221222
tm.assert_index_equal(ci.map(lambda x: 1),
222223
Index(np.array([1] * 5, dtype=np.int64), name='XXX'))
223224

pandas/tests/test_categorical.py

+1
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,7 @@ def test_map(self):
16641664
tm.assert_categorical_equal(result, exp)
16651665

16661666
result = c.map(lambda x: 1)
1667+
# GH 12766: Return an index not an array
16671668
tm.assert_index_equal(result, Index(np.array([1] * 5, dtype=np.int64)))
16681669

16691670

0 commit comments

Comments
 (0)