Skip to content

Commit fa4358d

Browse files
committed
API: Added axis argument to rename
xref: pandas-dev#12392
1 parent 22515f5 commit fa4358d

File tree

4 files changed

+105
-2
lines changed

4 files changed

+105
-2
lines changed

doc/source/whatsnew/v0.21.0.txt

+13
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ For example:
109109
# the following is now equivalent
110110
df.drop(columns=['B', 'C'])
111111

112+
``rename`` now also accepts axis keyword
113+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114+
115+
The :meth:`~DataFrame.rename` method has gained the ``axis`` keyword as an
116+
alternative to specify the ``axis`` to target (:issue:`12392`).
117+
118+
.. ipython::
119+
120+
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
121+
df.rename(str.lower, axis='columns')
122+
123+
The ``.rename(columns=str.lower)`` style continues to work as before.
124+
112125
.. _whatsnew_0210.enhancements.categorical_dtype:
113126

114127
``CategoricalDtype`` for specifying categoricals

pandas/core/frame.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -2904,7 +2904,28 @@ def reindex_axis(self, labels, axis=0, method=None, level=None, copy=True,
29042904
limit=limit, fill_value=fill_value)
29052905

29062906
@Appender(_shared_docs['rename'] % _shared_doc_kwargs)
2907-
def rename(self, index=None, columns=None, **kwargs):
2907+
def rename(self, *args, index=None, columns=None, **kwargs):
2908+
nargs = len(args)
2909+
if 'axis' in kwargs and (index is not None or columns is not None):
2910+
raise TypeError("Cannot specify 'index' or 'columns' and 'axis' at"
2911+
" the same time. Specify either\n"
2912+
"\t.rename(mapping, axis=axis), or\n"
2913+
"\t.rename(index=index, columns=columns)")
2914+
if 'axis' in kwargs and nargs > 1:
2915+
raise TypeError("Cannot specify 'index', 'axis', and 'columns' at "
2916+
"the same time.")
2917+
if nargs > 2:
2918+
raise TypeError("Too many positional arguments")
2919+
2920+
if nargs and index is not None:
2921+
raise TypeError("rename() got multiple arguments for argumnet "
2922+
"'index'")
2923+
2924+
if index is None and nargs:
2925+
index = args[0]
2926+
if columns is None and nargs > 1:
2927+
columns = args[1]
2928+
29082929
return super(DataFrame, self).rename(index=index, columns=columns,
29092930
**kwargs)
29102931

pandas/core/generic.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -807,11 +807,20 @@ def swaplevel(self, i=-2, j=-1, axis=0):
807807
@Appender(_shared_docs['rename'] % dict(axes='axes keywords for this'
808808
' object', klass='NDFrame'))
809809
def rename(self, *args, **kwargs):
810-
811810
axes, kwargs = self._construct_axes_from_arguments(args, kwargs)
812811
copy = kwargs.pop('copy', True)
813812
inplace = kwargs.pop('inplace', False)
814813
level = kwargs.pop('level', None)
814+
axis = kwargs.pop("axis", None)
815+
816+
if axis:
817+
# At this point, we know the call was
818+
# rename(fn, axis=axis), so axes is always
819+
# {index: op, columns: None}
820+
axis = self._get_axis_name(axis)
821+
op = axes['index']
822+
axes['index'] = None
823+
axes[axis] = op
815824

816825
if kwargs:
817826
raise TypeError('rename() got an unexpected keyword '

pandas/tests/frame/test_alter_axes.py

+60
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,66 @@ def test_rename_objects(self):
837837
assert 'FOO' in renamed
838838
assert 'foo' not in renamed
839839

840+
def test_rename_columns(self):
841+
df = pd.DataFrame({"A": [1, 2], "B": [1, 2]}, index=['X', 'Y'])
842+
expected = pd.DataFrame({"a": [1, 2], "b": [1, 2]}, index=['X', 'Y'])
843+
844+
result = df.rename(str.lower, axis=1)
845+
assert_frame_equal(result, expected)
846+
847+
result = df.rename(str.lower, axis='columns')
848+
assert_frame_equal(result, expected)
849+
850+
result = df.rename({"A": 'a', 'B': 'b'}, axis=1)
851+
assert_frame_equal(result, expected)
852+
853+
result = df.rename({"A": 'a', 'B': 'b'}, axis='columns')
854+
assert_frame_equal(result, expected)
855+
856+
# Index
857+
expected = pd.DataFrame({"A": [1, 2], "B": [1, 2]}, index=['x', 'y'])
858+
result = df.rename(str.lower, axis=0)
859+
assert_frame_equal(result, expected)
860+
861+
result = df.rename(str.lower, axis='index')
862+
assert_frame_equal(result, expected)
863+
864+
result = df.rename({'X': 'x', 'Y': 'y'}, axis=0)
865+
assert_frame_equal(result, expected)
866+
867+
result = df.rename({'X': 'x', 'Y': 'y'}, axis='index')
868+
assert_frame_equal(result, expected)
869+
870+
def test_rename_raises(self):
871+
df = pd.DataFrame({"A": [1, 2], "B": [1, 2]}, index=['0', '1'])
872+
873+
# Named target and axis
874+
with tm.assert_raises_regex(TypeError, None):
875+
df.rename(index=str.lower, axis=1)
876+
877+
with tm.assert_raises_regex(TypeError, None):
878+
df.rename(index=str.lower, axis='columns')
879+
880+
with tm.assert_raises_regex(TypeError, None):
881+
df.rename(index=str.lower, axis=0)
882+
883+
with tm.assert_raises_regex(TypeError, None):
884+
df.rename(index=str.lower, axis='columns')
885+
886+
with tm.assert_raises_regex(TypeError, None):
887+
df.rename(columns=str.lower, axis='columns')
888+
889+
# Multiple targets and axis
890+
with tm.assert_raises_regex(TypeError, None):
891+
df.rename(str.lower, str.lower, axis='columns')
892+
893+
# Too many targets
894+
with tm.assert_raises_regex(TypeError, None):
895+
df.rename(str.lower, str.lower, str.lower)
896+
897+
with tm.assert_raises_regex(TypeError, None):
898+
df.rename(str.lower, index=str.lower)
899+
840900
def test_assign_columns(self):
841901
self.frame['hi'] = 'there'
842902

0 commit comments

Comments
 (0)