Skip to content

Commit fa0ed70

Browse files
author
tp
committed
Categorical.rename_categories can take a callable
1 parent 07d8c2d commit fa0ed70

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

doc/source/whatsnew/v0.22.0.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ Other Enhancements
139139
- :func:`read_excel()` has gained the ``nrows`` parameter (:issue:`16645`)
140140
- :func:``DataFrame.to_json`` and ``Series.to_json`` now accept an ``index`` argument which allows the user to exclude the index from the JSON output (:issue:`17394`)
141141
- ``IntervalIndex.to_tuples()`` has gained the ``na_tuple`` parameter to control whether NA is returned as a tuple of NA, or NA itself (:issue:`18756`)
142+
- ``Categorical.rename_categories`` can how take a callable as its argument (:issue:`18862`)
142143

143144
.. _whatsnew_0220.api_breaking:
144145

pandas/core/categorical.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ def rename_categories(self, new_categories, inplace=False):
844844
845845
Parameters
846846
----------
847-
new_categories : list-like or dict-like
847+
new_categories : list-like, dict-like or callable
848848
849849
* list-like: all items must be unique and the number of items in
850850
the new categories must match the existing number of categories.
@@ -854,6 +854,10 @@ def rename_categories(self, new_categories, inplace=False):
854854
are passed through and extra categories in the mapping are
855855
ignored. *New in version 0.21.0*.
856856
857+
* callable : a callable that is called on all items in the old
858+
categories and whose return values comprise the new categories.
859+
*New in version 0.22.0*.
860+
857861
.. warning::
858862
859863
Currently, Series are considered list like. In a future version
@@ -890,6 +894,12 @@ def rename_categories(self, new_categories, inplace=False):
890894
>>> c.rename_categories({'a': 'A', 'c': 'C'})
891895
[A, A, b]
892896
Categories (2, object): [A, b]
897+
898+
You may also provide a callable to create the new categories
899+
900+
>>> c.rename_categories(lambda x: x.upper())
901+
[A, A, B]
902+
Categories (2, object): [A, B]
893903
"""
894904
inplace = validate_bool_kwarg(inplace, 'inplace')
895905
cat = self if inplace else self.copy()
@@ -906,6 +916,8 @@ def rename_categories(self, new_categories, inplace=False):
906916
if is_dict_like(new_categories):
907917
cat.categories = [new_categories.get(item, item)
908918
for item in cat.categories]
919+
elif callable(new_categories):
920+
cat.categories = [new_categories(item) for item in cat.categories]
909921
else:
910922
cat.categories = new_categories
911923
if not inplace:

pandas/tests/categorical/test_api.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,14 @@ def test_rename_categories(self):
7171

7272
exp_cat = Index(["a", "b", "c"])
7373
tm.assert_index_equal(cat.categories, exp_cat)
74-
res = cat.rename_categories([1, 2, 3], inplace=True)
74+
75+
# GH18862
76+
result = cat.rename_categories(lambda x: x.upper())
77+
expected = Categorical(["A", "B", "C", "A"])
78+
tm.assert_categorical_equal(result, expected)
7579

7680
# and now inplace
81+
res = cat.rename_categories([1, 2, 3], inplace=True)
7782
assert res is None
7883
tm.assert_numpy_array_equal(cat.__array__(), np.array([1, 2, 3, 1],
7984
dtype=np.int64))

0 commit comments

Comments
 (0)