Skip to content

Commit 16c4a9f

Browse files
committed
Allow for dict-like categorical renaming
1 parent 37e23d0 commit 16c4a9f

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed

doc/source/categorical.rst

+4
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ by using the :func:`Categorical.rename_categories` method:
206206
s.cat.categories = ["Group %s" % g for g in s.cat.categories]
207207
s
208208
s.cat.rename_categories([1,2,3])
209+
s
210+
# You can also pass a dict-like object to map the renaming
211+
s.cat.rename_categories({1: 'x', 2: 'y', 3: 'z'})
212+
s
209213
210214
.. note::
211215

doc/source/whatsnew/v0.21.0.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ Other Enhancements
114114
- :func:`pd.read_sas()` now recognizes much more of the most frequently used date (datetime) formats in SAS7BDAT files (:issue:`15871`).
115115
- :func:`DataFrame.items` and :func:`Series.items` is now present in both Python 2 and 3 and is lazy in all cases (:issue:`13918`, :issue:`17213`)
116116
- :func:`Styler.where` has been implemented. It is as a convenience for :func:`Styler.applymap` and enables simple DataFrame styling on the Jupyter notebook (:issue:`17474`).
117-
117+
- :func:`Categorical.rename_categories` now accepts a dict-like argument as `new_categories`, and only updates the categories found in that dict. (:issue:`17336`)
118+
- :func:`MultiIndex.is_monotonic_decreasing` has been implemented. Previously returned ``False`` in all cases. (:issue:`16554`)
118119

119120

120121
.. _whatsnew_0210.api_breaking:
@@ -525,6 +526,8 @@ Plotting
525526
^^^^^^^^
526527
- Bug in plotting methods using ``secondary_y`` and ``fontsize`` not setting secondary axis font size (:issue:`12565`)
527528
- Bug when plotting ``timedelta`` and ``datetime`` dtypes on y-axis (:issue:`16953`)
529+
- Line plots no longer assume monotonic x data when calculating xlims, they show the entire lines now even for unsorted x data. (:issue:`11310`)(:issue:`11471`)
530+
- With matplotlib 2.0.0 and above, calculation of x limits for line plots is left to matplotlib, so that its new default settings are applied. (:issue:`15495`)
528531
- Bug in ``Series.plot.bar`` or ``DataFramee.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`)
529532

530533

pandas/core/categorical.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
is_categorical_dtype,
2626
is_integer_dtype, is_bool,
2727
is_list_like, is_sequence,
28-
is_scalar)
28+
is_scalar,
29+
is_dict_like)
2930
from pandas.core.common import is_null_slice, _maybe_box_datetimelike
3031

3132
from pandas.core.algorithms import factorize, take_1d, unique1d
@@ -824,7 +825,11 @@ def rename_categories(self, new_categories, inplace=False):
824825
"""
825826
inplace = validate_bool_kwarg(inplace, 'inplace')
826827
cat = self if inplace else self.copy()
827-
cat.categories = new_categories
828+
if is_dict_like(new_categories):
829+
cat.categories = [new_categories.get(item, item)
830+
for item in cat.categories]
831+
else:
832+
cat.categories = new_categories
828833
if not inplace:
829834
return cat
830835

pandas/tests/test_categorical.py

+29
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,35 @@ def test_rename_categories(self):
983983
with pytest.raises(ValueError):
984984
cat.rename_categories([1, 2])
985985

986+
def test_rename_categories_dict(self):
987+
# GH 17336
988+
cat = pd.Categorical(['a', 'b', 'c', 'd'])
989+
res = cat.rename_categories({'a': 4, 'b': 3, 'c': 2, 'd': 1})
990+
expected = Index([4, 3, 2, 1])
991+
tm.assert_index_equal(res.categories, expected)
992+
# Test for inplace
993+
res = cat.rename_categories({'a': 4, 'b': 3, 'c': 2, 'd': 1},
994+
inplace=True)
995+
assert res is None
996+
997+
tm.assert_index_equal(cat.categories, expected)
998+
# Test for dicts of smaller length
999+
cat = pd.Categorical(['a', 'b', 'c', 'd'])
1000+
res = cat.rename_categories({'a': 1, 'c': 3})
1001+
expected = Index([1, 'b', 3, 'd'])
1002+
tm.assert_index_equal(res.categories, expected)
1003+
# Test for dicts with bigger length
1004+
cat = pd.Categorical(['a', 'b', 'c', 'd'])
1005+
res = cat.rename_categories({'a': 1, 'b': 2, 'c': 3,
1006+
'd': 4, 'e': 5, 'f': 6})
1007+
expected = Index([1, 2, 3, 4])
1008+
tm.assert_index_equal(res.categories, expected)
1009+
# Test for dicts with no items from old categories
1010+
cat = pd.Categorical(['a', 'b', 'c', 'd'])
1011+
res = cat.rename_categories({'f': 1, 'g': 3})
1012+
expected = Index(['a', 'b', 'c', 'd'])
1013+
tm.assert_index_equal(res.categories, expected)
1014+
9861015
@pytest.mark.parametrize('codes, old, new, expected', [
9871016
([0, 1], ['a', 'b'], ['a', 'b'], [0, 1]),
9881017
([0, 1], ['b', 'a'], ['b', 'a'], [0, 1]),

0 commit comments

Comments
 (0)