53
53
isidentifier , set_function_name , cPickle as pkl )
54
54
from pandas .core .ops import _align_method_FRAME
55
55
import 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 )
57
58
from pandas .util ._validators import validate_bool_kwarg , validate_fillna_kwargs
58
59
from pandas .core import config
59
60
@@ -1079,20 +1080,6 @@ def rename(self, *args, **kwargs):
1079
1080
if com .count_not_none (* axes .values ()) == 0 :
1080
1081
raise TypeError ('must pass an index to rename' )
1081
1082
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
-
1096
1083
self ._consolidate_inplace ()
1097
1084
result = self if inplace else self .copy (deep = copy )
1098
1085
@@ -1101,7 +1088,7 @@ def f(x):
1101
1088
v = axes .get (self ._AXIS_NAMES [axis ])
1102
1089
if v is None :
1103
1090
continue
1104
- f = _get_rename_function (v )
1091
+ f = com . _get_rename_function (v )
1105
1092
1106
1093
baxis = self ._get_block_manager_axis (axis )
1107
1094
if level is not None :
@@ -1115,16 +1102,28 @@ def f(x):
1115
1102
else :
1116
1103
return result .__finalize__ (self )
1117
1104
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 ):
1119
1108
"""
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.
1121
1111
1122
1112
Parameters
1123
1113
----------
1124
1114
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
1128
1127
copy : boolean, default True
1129
1128
Also copy underlying data.
1130
1129
inplace : boolean, default False
@@ -1143,6 +1142,23 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
1143
1142
deprecated and will be removed in a future version. Use ``rename``
1144
1143
instead.
1145
1144
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
+
1146
1162
See Also
1147
1163
--------
1148
1164
pandas.Series.rename : Alter Series index labels or name
@@ -1176,20 +1192,94 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
1176
1192
0 1 4
1177
1193
1 2 5
1178
1194
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
+
1180
1244
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 )
1185
1262
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
1193
1283
1194
1284
def _set_axis_name (self , name , axis = 0 , inplace = False ):
1195
1285
"""
0 commit comments