6565 _values_from_object ,
6666 _maybe_box_datetimelike ,
6767 _dict_compat ,
68+ _all_not_none ,
6869 standardize_mapping )
6970from pandas .core .generic import NDFrame , _shared_docs
7071from pandas .core .index import (Index , MultiIndex , _ensure_index ,
111112 optional_by = """
112113 by : str or list of str
113114 Name or list of names which refer to the axis items.""" ,
114- versionadded_to_excel = '' )
115+ versionadded_to_excel = '' ,
116+ optional_labels = """labels : array-like, optional
117+ New labels / index to conform the axis specified by 'axis' to.""" ,
118+ optional_axis = """axis : int or str, optional
119+ Axis to target. Can be either the axis name ('index', 'columns')
120+ or number (0, 1).""" ,
121+ )
115122
116123_numeric_only_doc = """numeric_only : boolean, default None
117124 Include only float, int, boolean data. If None, will attempt to use
@@ -2776,6 +2783,47 @@ def reindexer(value):
27762783
27772784 return np .atleast_2d (np .asarray (value ))
27782785
2786+ def _validate_axis_style_args (self , arg , arg_name , index , columns ,
2787+ axis , method_name ):
2788+ if axis is not None :
2789+ # Using "axis" style, along with a positional arg
2790+ # Both index and columns should be None then
2791+ axis = self ._get_axis_name (axis )
2792+ if index is not None or columns is not None :
2793+ msg = (
2794+ "Can't specify both 'axis' and 'index' or 'columns'. "
2795+ "Specify either\n "
2796+ "\t .{method_name}.rename({arg_name}, axis=axis), or\n "
2797+ "\t .{method_name}.rename(index=index, columns=columns)"
2798+ ).format (arg_name = arg_name , method_name = method_name )
2799+ raise TypeError (msg )
2800+ if axis == 'index' :
2801+ index = arg
2802+ elif axis == 'columns' :
2803+ columns = arg
2804+
2805+ elif _all_not_none (arg , index , columns ):
2806+ msg = (
2807+ "Cannot specify all of '{arg_name}', 'index', and 'columns'. "
2808+ "Specify either {arg_name} and 'axis', or 'index' and "
2809+ "'columns'."
2810+ ).format (arg_name = arg_name )
2811+ raise TypeError (msg )
2812+
2813+ elif _all_not_none (arg , index ):
2814+ # This is the "ambiguous" case, so emit a warning
2815+ msg = (
2816+ "Interpreting call to '.{method_name}(a, b)' as "
2817+ "'.{method_name}(index=a, columns=b)'. "
2818+ "Use keyword arguments to remove any ambiguity."
2819+ ).format (method_name = method_name )
2820+ warnings .warn (msg , stacklevel = 3 )
2821+ index , columns = arg , index
2822+ elif index is None :
2823+ # This is for the default axis, like reindex([0, 1])
2824+ index = arg
2825+ return index , columns
2826+
27792827 @property
27802828 def _series (self ):
27812829 result = {}
@@ -2902,7 +2950,11 @@ def align(self, other, join='outer', axis=None, level=None, copy=True,
29022950 broadcast_axis = broadcast_axis )
29032951
29042952 @Appender (_shared_docs ['reindex' ] % _shared_doc_kwargs )
2905- def reindex (self , index = None , columns = None , ** kwargs ):
2953+ def reindex (self , labels = None , index = None , columns = None , axis = None ,
2954+ ** kwargs ):
2955+ index , columns = self ._validate_axis_style_args (labels , 'labels' ,
2956+ index , columns ,
2957+ axis , 'reindex' )
29062958 return super (DataFrame , self ).reindex (index = index , columns = columns ,
29072959 ** kwargs )
29082960
@@ -2914,8 +2966,84 @@ def reindex_axis(self, labels, axis=0, method=None, level=None, copy=True,
29142966 method = method , level = level , copy = copy ,
29152967 limit = limit , fill_value = fill_value )
29162968
2917- @Appender (_shared_docs ['rename' ] % _shared_doc_kwargs )
2918- def rename (self , index = None , columns = None , ** kwargs ):
2969+ def rename (self , mapper = None , index = None , columns = None , axis = None ,
2970+ ** kwargs ):
2971+ """Alter axes labels.
2972+
2973+ Function / dict values must be unique (1-to-1). Labels not contained in
2974+ a dict / Series will be left as-is. Extra labels listed don't throw an
2975+ error.
2976+
2977+ See the :ref:`user guide <basics.rename>` for more.
2978+
2979+ Parameters
2980+ ----------
2981+ mapper, index, columns : dict-like or function, optional
2982+ dict-like or functions transformations to apply to
2983+ that axis' values. Use either ``mapper`` and ``axis`` to
2984+ specify the axis to target with ``mapper``, or ``index`` and
2985+ ``columns``.
2986+ axis : int or str, optional
2987+ Axis to target with ``mapper``. Can be either the axis name
2988+ ('index', 'columns') or number (0, 1). The default is 'index'.
2989+ copy : boolean, default True
2990+ Also copy underlying data
2991+ inplace : boolean, default False
2992+ Whether to return a new %(klass)s. If True then value of copy is
2993+ ignored.
2994+ level : int or level name, default None
2995+ In case of a MultiIndex, only rename labels in the specified
2996+ level.
2997+
2998+ Returns
2999+ -------
3000+ renamed : DataFrame
3001+
3002+ See Also
3003+ --------
3004+ pandas.DataFrame.rename_axis
3005+
3006+ Examples
3007+ --------
3008+
3009+ ``DataFrame.rename`` supports two calling conventions
3010+
3011+ * ``(index=index_mapper, columns=columns_mapper, ...)
3012+ * ``(mapper, axis={'index', 'columns'}, ...)
3013+
3014+ We *highly* recommend using keyword arguments to clarify your
3015+ intent.
3016+
3017+ >>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
3018+ >>> df.rename(index=str, columns={"A": "a", "B": "c"})
3019+ a c
3020+ 0 1 4
3021+ 1 2 5
3022+ 2 3 6
3023+
3024+ >>> df.rename(index=str, columns={"A": "a", "C": "c"})
3025+ a B
3026+ 0 1 4
3027+ 1 2 5
3028+ 2 3 6
3029+
3030+ Using axis-style parameters
3031+
3032+ >>> df.rename(str.lower, axis='columns')
3033+ a b
3034+ 0 1 4
3035+ 1 2 5
3036+ 2 3 6
3037+
3038+ >>> df.rename({1: 2, 2: 4}, axis='index')
3039+ A B
3040+ 0 1 4
3041+ 2 2 5
3042+ 4 3 6
3043+ """
3044+ index , columns = self ._validate_axis_style_args (mapper , 'mapper' ,
3045+ index , columns ,
3046+ axis , 'rename' )
29193047 return super (DataFrame , self ).rename (index = index , columns = columns ,
29203048 ** kwargs )
29213049
0 commit comments