5353 isidentifier , set_function_name , cPickle as pkl )
5454from pandas .core .ops import _align_method_FRAME
5555import pandas .core .nanops as nanops
56- from pandas .util ._decorators import Appender , Substitution
56+ from pandas .util ._decorators import (Appender , Substitution ,
57+ rewrite_axis_style_signature )
5758from pandas .util ._validators import validate_bool_kwarg , validate_fillna_kwargs
5859from pandas .core import config
5960
@@ -1079,20 +1080,6 @@ def rename(self, *args, **kwargs):
10791080 if com .count_not_none (* axes .values ()) == 0 :
10801081 raise TypeError ('must pass an index to rename' )
10811082
1082- # renamer function if passed a dict
1083- def _get_rename_function (mapper ):
1084- if isinstance (mapper , (dict , ABCSeries )):
1085-
1086- def f (x ):
1087- if x in mapper :
1088- return mapper [x ]
1089- else :
1090- return x
1091- else :
1092- f = mapper
1093-
1094- return f
1095-
10961083 self ._consolidate_inplace ()
10971084 result = self if inplace else self .copy (deep = copy )
10981085
@@ -1101,7 +1088,7 @@ def f(x):
11011088 v = axes .get (self ._AXIS_NAMES [axis ])
11021089 if v is None :
11031090 continue
1104- f = _get_rename_function (v )
1091+ f = com . _get_rename_function (v )
11051092
11061093 baxis = self ._get_block_manager_axis (axis )
11071094 if level is not None :
@@ -1115,16 +1102,28 @@ def f(x):
11151102 else :
11161103 return result .__finalize__ (self )
11171104
1118- def rename_axis (self , mapper , axis = 0 , copy = True , inplace = False ):
1105+ @rewrite_axis_style_signature ('mapper' , [('copy' , True ),
1106+ ('inplace' , False )])
1107+ def rename_axis (self , mapper = None , ** kwargs ):
11191108 """
1120- Alter the name of the index or columns.
1109+ Alter the name of the index or name of Index object that is the
1110+ columns.
11211111
11221112 Parameters
11231113 ----------
11241114 mapper : scalar, list-like, optional
1125- Value to set as the axis name attribute.
1126- axis : {0 or 'index', 1 or 'columns'}, default 0
1127- The index or the name of the axis.
1115+ Value to set the axis name attribute.
1116+ index, columns : scalar, list-like, dict-like or function, optional
1117+ dict-like or functions transformations to apply to
1118+ that axis' values.
1119+
1120+ Use either ``mapper`` and ``axis`` to
1121+ specify the axis to target with ``mapper``, or ``index``
1122+ and/or ``columns``.
1123+
1124+ .. versionchanged:: 0.24.0
1125+
1126+ axis : int or string, default 0
11281127 copy : boolean, default True
11291128 Also copy underlying data.
11301129 inplace : boolean, default False
@@ -1143,6 +1142,23 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
11431142 deprecated and will be removed in a future version. Use ``rename``
11441143 instead.
11451144
1145+ ``DataFrame.rename_axis`` supports two calling conventions
1146+
1147+ * ``(index=index_mapper, columns=columns_mapper, ...)``
1148+ * ``(mapper, axis={'index', 'columns'}, ...)``
1149+
1150+ The first calling convention will only modify the names of
1151+ the index and/or the names of the Index object that is the columns.
1152+ In this case, the parameter ``copy`` is ignored.
1153+
1154+ The second calling convention will modify the names of the
1155+ the corresponding index if mapper is a list or a scalar.
1156+ However, if mapper is dict-like or a function, it will use the
1157+ deprecated behavior of modifying the axis *labels*.
1158+
1159+ We *highly* recommend using keyword arguments to clarify your
1160+ intent.
1161+
11461162 See Also
11471163 --------
11481164 pandas.Series.rename : Alter Series index labels or name
@@ -1176,20 +1192,94 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
11761192 0 1 4
11771193 1 2 5
11781194 2 3 6
1179- """
1195+
1196+ >>> mi = pd.MultiIndex.from_product([['a', 'b', 'c'], [1, 2]],
1197+ ... names=['let','num'])
1198+ >>> df = pd.DataFrame({'x': [i for i in range(len(mi))],
1199+ ... 'y' : [i*10 for i in range(len(mi))]},
1200+ ... index=mi)
1201+ >>> df.rename_axis(index={'num' : 'n'})
1202+ x y
1203+ let n
1204+ a 1 0 0
1205+ 2 1 10
1206+ b 1 2 20
1207+ 2 3 30
1208+ c 1 4 40
1209+ 2 5 50
1210+
1211+ >>> cdf = df.rename_axis(columns='col')
1212+ >>> cdf
1213+ col x y
1214+ let num
1215+ a 1 0 0
1216+ 2 1 10
1217+ b 1 2 20
1218+ 2 3 30
1219+ c 1 4 40
1220+ 2 5 50
1221+
1222+ >>> cdf.rename_axis(columns=str.upper)
1223+ COL x y
1224+ let num
1225+ a 1 0 0
1226+ 2 1 10
1227+ b 1 2 20
1228+ 2 3 30
1229+ c 1 4 40
1230+ 2 5 50
1231+
1232+ """
1233+ axes , kwargs = self ._construct_axes_from_arguments ((), kwargs )
1234+ copy = kwargs .pop ('copy' , True )
1235+ inplace = kwargs .pop ('inplace' , False )
1236+ axis = kwargs .pop ('axis' , 0 )
1237+ if axis is not None :
1238+ axis = self ._get_axis_number (axis )
1239+
1240+ if kwargs :
1241+ raise TypeError ('rename_axis() got an unexpected keyword '
1242+ 'argument "{0}"' .format (list (kwargs .keys ())[0 ]))
1243+
11801244 inplace = validate_bool_kwarg (inplace , 'inplace' )
1181- non_mapper = is_scalar (mapper ) or (is_list_like (mapper ) and not
1182- is_dict_like (mapper ))
1183- if non_mapper :
1184- return self ._set_axis_name (mapper , axis = axis , inplace = inplace )
1245+
1246+ if (mapper is not None ):
1247+ # Use v0.23 behavior if a scalar or list
1248+ non_mapper = is_scalar (mapper ) or (is_list_like (mapper ) and not
1249+ is_dict_like (mapper ))
1250+ if non_mapper :
1251+ return self ._set_axis_name (mapper , axis = axis , inplace = inplace )
1252+ else :
1253+ # Deprecated (v0.21) behavior is if mapper is specified,
1254+ # and not a list or scalar, then call rename
1255+ msg = ("Using 'rename_axis' to alter labels is deprecated. "
1256+ "Use '.rename' instead" )
1257+ warnings .warn (msg , FutureWarning , stacklevel = 3 )
1258+ axis = self ._get_axis_name (axis )
1259+ d = {'copy' : copy , 'inplace' : inplace }
1260+ d [axis ] = mapper
1261+ return self .rename (** d )
11851262 else :
1186- msg = ("Using 'rename_axis' to alter labels is deprecated. "
1187- "Use '.rename' instead" )
1188- warnings .warn (msg , FutureWarning , stacklevel = 2 )
1189- axis = self ._get_axis_name (axis )
1190- d = {'copy' : copy , 'inplace' : inplace }
1191- d [axis ] = mapper
1192- return self .rename (** d )
1263+ # Use new behavior. Means that index and/or columns
1264+ # is specified
1265+ result = self if inplace else self .copy (deep = copy )
1266+
1267+ for axis in lrange (self ._AXIS_LEN ):
1268+ v = axes .get (self ._AXIS_NAMES [axis ])
1269+ if v is None :
1270+ continue
1271+ non_mapper = is_scalar (v ) or (is_list_like (v ) and not
1272+ is_dict_like (v ))
1273+ if non_mapper :
1274+ newnames = v
1275+ else :
1276+ f = com ._get_rename_function (v )
1277+ curnames = self ._get_axis (axis ).names
1278+ newnames = [f (name ) for name in curnames ]
1279+ result ._set_axis_name (newnames , axis = axis ,
1280+ inplace = True )
1281+ if not inplace :
1282+ return result
11931283
11941284 def _set_axis_name (self , name , axis = 0 , inplace = False ):
11951285 """
0 commit comments