Repository: pandas-dev/pandas

Issue:
API: Allow dictionary argument in rename_axis to change some names of MultiIndex
#### Code Sample, a copy-pastable example if possible

```python
mi = pd.MultiIndex.from_product([['a','b','c'],[1,2]], names=['ll','nn'])
df = pd.DataFrame({'x': [i for i in range(len(mi))], 'y' : [i*10 for i in range(len(mi))]}, index=mi)
df.rename(columns={'x':'z'})  # This works to change name of one column
df.rename_axis({'x' : 'z'}, axis='columns')  # This also works to change name of one column (but you get a deprecation warning)
df.rename(index={'nn':'zz'}) # This does not work to change name of one level of a MultiIndex
df.rename_axis({'nn' : 'zz'}, axis='index') # This does not work to change name of one level of a MultiIndex
```
#### Problem description

Ideally, if you call `df.rename_axis(dict, axis='index')`, only the names specified in the dictionary would be changed in the corresponding `MultiIndex`


#### Expected Output
For the expression
```
df.rename_axis({'nn' : 'zz'}, axis='index')
```
the output should be:
```
       x   y
zz ll       
1  a   0   0
   b   1  10
   c   2  20
2  a   3  30
   b   4  40
   c   5  50
```

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.6.4.final.0
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.22.0
pytest: 3.3.2
pip: 9.0.1
setuptools: 38.4.0
Cython: 0.27.3
numpy: 1.14.0
scipy: 1.0.0
pyarrow: None
xarray: None
IPython: 6.2.1
sphinx: 1.6.6
patsy: 0.5.0
dateutil: 2.6.1
pytz: 2017.3
blosc: None
bottleneck: 1.2.1
tables: 3.4.2
numexpr: 2.6.4
feather: None
matplotlib: 2.1.2
openpyxl: 2.4.10
xlrd: 1.1.0
xlwt: 1.3.0
xlsxwriter: 1.0.2
lxml: 4.1.1
bs4: 4.6.0
html5lib: 1.0.1
sqlalchemy: 1.2.1
pymysql: 0.7.11.None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
In [ ]:

​
</details>



Discussion:
duplicate of #4160 a pull-request is welcome.

MI rename is entirely broken.
This is another issue. https://github.com/pandas-dev/pandas/issues/4160 is about renaming *labels* in a MultiIndex (with `rename`), this issue is about renaming MultiIndex level *names* (with `rename_index`)
@jorisvandenbossche Yes, this is about changing the level names, but using `rename_axis` (not `rename_index` - that doesn't exist!)
So in order to allow this functionality (using a mapper to change some names of a `MultiIndex`) now without removing the deprecated behavior, I propose to add a parameter `rename_names=False` that keeps the deprecated behavior, and then we flip it to `rename_names=True` when the deprecated behavior (passing a `dict` or function to change some names, which changes the labels) is removed.

Otherwise, I can't see how to add this functionality until some future version where we can officially remove the deprecated behavior.  Comments from @jorisvandenbossche and @jreback welcome.
```
In [6]: mi = pd.MultiIndex.from_product([['a','b','c'],[1,2]], names=['ll','nn'])
   ...: df = pd.DataFrame({'x': [i for i in range(len(mi))], 'y' : [i*10 for i in range(len(mi))]}, index=mi)
   ...: 

In [7]: df.index = df.index.set_names('baz', level=1)

In [8]: df
Out[8]: 
        x   y
ll baz       
a  1    0   0
   2    1  10
b  1    2  20
   2    3  30
c  1    4  40
   2    5  50
```

@Dr-Irv you can just do this. this is quite idiomatic and should be used more anyhow.
@jreback Yes, but then I can't do the renaming inline, which is the capability that I'd like to have.

With the current `rename_axis`, I can rename *all* the names inline, but not individual ones. In other words, in your example:
```
df.rename_axis(['ll','baz'],axis='index')
```
produces the desired result, but then you have to specify *all* of the names, rather than just the ones you want to change.

Just like `rename` allows changing only some of the labels, I'd like to have `rename_axis` change some of the names.

sure you can, use ``inplace=True``. its completely non-idiomatic but you can use it
I am -1 on changing this and why I closed it.
@jreback I'm looking at this from having some cleanliness and symmetry in the API's.  Let's say that I have a `DataFrame` with lots of columns that has come from doing lots of computation, and it is indexed on a `MultiIndex` with multiple levels.  In a chained computation, I can write `df.rename(columns=dict(...))` to rename _some_ of the columns.  From my point of view, the names of the `MultiIndex` are just like columns. They just happen to be the index, i.e., like primary keys in a database. So I'd like to be able to do `df.rename_axis(dict(...), axis='index')` to change _some_ of the names in the index, and use that in a chained computation.
@jreback Here's an example that illustrates the need for rename_axis with an argument dictionary.  In this example, there are 2 DataFrames, (df3 and df2) and the contents of the indexes are exactly the same, except that one of the names of the index in df2 is different.  So if try to add the 2 Series, I get an error because the names of the indexes are different.  But if I change that single name, I can then do the add.
```

In [2]: mi3 = pd.MultiIndex.from_product([list('AB'),list('CD'),list('EF')], name
   ...: s=['AB', 'CD', 'EF'])
   ...: df3 = pd.DataFrame([i for i in range(len(mi3))], index=mi3, columns=['N']
   ...: )
   ...: df3
   ...:
Out[2]:
          N
AB CD EF
A  C  E   0
      F   1
   D  E   2
      F   3
B  C  E   4
      F   5
   D  E   6
      F   7

In [3]: df2 = df3.reorder_levels(['EF','CD','AB']).sort_index().reorder_levels(['
   ...: AB','CD','EF'])
   ...: df2.index.names = ['AB','CD','EF1']
   ...: df2
   ...:
Out[3]:
           N
AB CD EF1
A  C  E    0
B  C  E    4
A  D  E    2
B  D  E    6
A  C  F    1
B  C  F    5
A  D  F    3
B  D  F    7

In [4]: df3 + df2
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-4-b209b0c95b4e> in <module>()
----> 1 df3 + df2

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\ops.py in f(self, other, axis, level, fill_value)
   1493
   1494         if isinstance(other, ABCDataFrame):  # Another DataFrame
-> 1495             return self._combine_frame(other, na_op, fill_value, level)
   1496         elif isinstance(other, ABCSeries):
   1497             return _combine_series_frame(self, other, na_op,

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\frame.py in _combine_frame(self, other, func, fill_value, level)
   3967
   3968     def _combine_frame(self, other, func, fill_value=None, level=None):
-> 3969         this, other = self.align(other, join='outer', level=level, copy=False)
   3970         new_index, new_columns = this.index, this.columns
   3971

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\frame.py in align(self, other, join, axis, level, copy, fill_value, method, limit, fill_axis, broadcast_axis)
   3010                                             method=method, limit=limit,
   3011                                             fill_axis=fill_axis,
-> 3012                                             broadcast_axis=broadcast_axis)

   3013
   3014     @Appender(_shared_docs['reindex'] % _shared_doc_kwargs)

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\generic.py in align(self, other, join, axis, level, copy, fill_value, method, limit, fill_axis, broadcast_axis)
   6324                                      copy=copy, fill_value=fill_value,
   6325                                      method=method, limit=limit,
-> 6326                                      fill_axis=fill_axis)
   6327         elif isinstance(other, Series):
   6328             return self._align_series(other, join=join, axis=axis, level=level,

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\generic.py in _align_frame(self, other, join, axis, level, copy, fill_value, method, limit, fill_axis)
   6346             if not self.index.equals(other.index):
   6347                 join_index, ilidx, iridx = self.index.join(
-> 6348                     other.index, how=join, level=level, return_indexers=True)
   6349
   6350         if axis is None or axis == 1:

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\indexes\base.py in join(self, other, how, level, return_indexers, sort)
   3229             else:
   3230                 return self._join_multi(other, how=how,
-> 3231                                         return_indexers=return_indexers)
   3232
   3233         # join on the level

C:\EclipseWorkspaces\LiClipseWorkspace\pandas-dev\pandas36\pandas\core\indexes\base.py in _join_multi(self, other, how, return_indexers)
   3327                              "overlapping names")
   3328         if len(overlap) > 1:
-> 3329             raise NotImplementedError("merging with more than one level "
   3330                                       "overlap on a multi-index is not "
   3331                                       "implemented")

NotImplementedError: merging with more than one level overlap on a multi-index is not implemented
```
So now I change the name of the mismatched column:
```
In [5]: df3.index.names = ['AB','CD','EF1']
   ...: df3 + df2
   ...:
Out[5]:
            N
AB CD EF1
A  C  E     0
      F     2
   D  E     4
      F     6
B  C  E     8
      F    10
   D  E    12
      F    14
```
The example is convoluted, but what is happening in my application is that I have two Series.  In my application, the first Series `s1` has a 3-level MultiIndex, names are `['a','b','k1']`, and the other Series `s2` has a 3-level MultiIndex, names are `['a','b','k']`.  I now need to add them together.  That fails (as in the example above) because the level names are different.  But if I could do in my example:
```
df3.rename_axis({'EF' : 'EF1'}) + df2
```
or
```
df3 + df2.rename_axis({'EF1':'EF'}) 
```
I wouldn't have to permanently change the index of `df3`, which is needed elsewhere with the original index names.

Jeff, you closed it as a duplicate (which it wasn't after further thought)

@Dr-Irv I am personally in general fine with the idea. But, I don't really like the introduction of a temporary keyword like `rename_names=True`. 
But I was thinking of another way we might get around the backwards compatibility / deprecation. For `reindex` and `rename` we harmonized the `labels, axis=1/0` idiom and the `index=labels, columns=labels` idiom (before each function did one of them, now both accept both ways to specify the columns or index to change). `rename_axis` currently uses the `axis` keyword, but we could also introduce here the `index` and `columns` keywords, and for those we can directly use the new behaviour. So something like `df.rename_axis(index={'EF1':'EF'})` could then work.

@jreback the reason I am fine with this is because it feels consistent with how we do things in other places in pandas. Eg rename with a dict let's you rename specific values of the columns/index without needing to specify them all, here it would be very similar but for the columns/index level names.  

Resolving patch:
diff --git a/pandas/core/common.py b/pandas/core/common.py
--- a/pandas/core/common.py
+++ b/pandas/core/common.py
@@ -454,3 +454,21 @@ def _pipe(obj, func, *args, **kwargs):
         return func(*args, **kwargs)
     else:
         return func(obj, *args, **kwargs)
+
+
+def _get_rename_function(mapper):
+    """
+    Returns a function that will map names/labels, dependent if mapper
+    is a dict, Series or just a function.
+    """
+    if isinstance(mapper, (compat.Mapping, ABCSeries)):
+
+        def f(x):
+            if x in mapper:
+                return mapper[x]
+            else:
+                return x
+    else:
+        f = mapper
+
+    return f
diff --git a/pandas/core/generic.py b/pandas/core/generic.py
--- a/pandas/core/generic.py
+++ b/pandas/core/generic.py
@@ -53,7 +53,8 @@
                            isidentifier, set_function_name, cPickle as pkl)
 from pandas.core.ops import _align_method_FRAME
 import pandas.core.nanops as nanops
-from pandas.util._decorators import Appender, Substitution
+from pandas.util._decorators import (Appender, Substitution,
+                                     rewrite_axis_style_signature)
 from pandas.util._validators import validate_bool_kwarg, validate_fillna_kwargs
 from pandas.core import config
 
@@ -1079,20 +1080,6 @@ def rename(self, *args, **kwargs):
         if com.count_not_none(*axes.values()) == 0:
             raise TypeError('must pass an index to rename')
 
-        # renamer function if passed a dict
-        def _get_rename_function(mapper):
-            if isinstance(mapper, (dict, ABCSeries)):
-
-                def f(x):
-                    if x in mapper:
-                        return mapper[x]
-                    else:
-                        return x
-            else:
-                f = mapper
-
-            return f
-
         self._consolidate_inplace()
         result = self if inplace else self.copy(deep=copy)
 
@@ -1101,7 +1088,7 @@ def f(x):
             v = axes.get(self._AXIS_NAMES[axis])
             if v is None:
                 continue
-            f = _get_rename_function(v)
+            f = com._get_rename_function(v)
 
             baxis = self._get_block_manager_axis(axis)
             if level is not None:
@@ -1115,16 +1102,28 @@ def f(x):
         else:
             return result.__finalize__(self)
 
-    def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
+    @rewrite_axis_style_signature('mapper', [('copy', True),
+                                             ('inplace', False)])
+    def rename_axis(self, mapper=None, **kwargs):
         """
-        Alter the name of the index or columns.
+        Alter the name of the index or name of Index object that is the
+        columns.
 
         Parameters
         ----------
         mapper : scalar, list-like, optional
-            Value to set as the axis name attribute.
-        axis : {0 or 'index', 1 or 'columns'}, default 0
-            The index or the name of the axis.
+            Value to set the axis name attribute.
+        index, columns : scalar, list-like, dict-like or function, optional
+            dict-like or functions transformations to apply to
+            that axis' values.
+
+            Use either ``mapper`` and ``axis`` to
+            specify the axis to target with ``mapper``, or ``index``
+            and/or ``columns``.
+
+            .. versionchanged:: 0.24.0
+
+        axis : int or string, default 0
         copy : boolean, default True
             Also copy underlying data.
         inplace : boolean, default False
@@ -1143,6 +1142,23 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
         deprecated and will be removed in a future version. Use ``rename``
         instead.
 
+        ``DataFrame.rename_axis`` supports two calling conventions
+
+        * ``(index=index_mapper, columns=columns_mapper, ...)``
+        * ``(mapper, axis={'index', 'columns'}, ...)``
+
+        The first calling convention will only modify the names of
+        the index and/or the names of the Index object that is the columns.
+        In this case, the parameter ``copy`` is ignored.
+
+        The second calling convention will modify the names of the
+        the corresponding index if mapper is a list or a scalar.
+        However, if mapper is dict-like or a function, it will use the
+        deprecated behavior of modifying the axis *labels*.
+
+        We *highly* recommend using keyword arguments to clarify your
+        intent.
+
         See Also
         --------
         pandas.Series.rename : Alter Series index labels or name
@@ -1176,20 +1192,94 @@ def rename_axis(self, mapper, axis=0, copy=True, inplace=False):
         0    1  4
         1    2  5
         2    3  6
-        """
+
+        >>> mi = pd.MultiIndex.from_product([['a', 'b', 'c'], [1, 2]],
+        ...                                 names=['let','num'])
+        >>> df = pd.DataFrame({'x': [i for i in range(len(mi))],
+        ...                    'y' : [i*10 for i in range(len(mi))]},
+        ...                    index=mi)
+        >>> df.rename_axis(index={'num' : 'n'})
+               x   y
+        let n
+        a   1  0   0
+            2  1  10
+        b   1  2  20
+            2  3  30
+        c   1  4  40
+            2  5  50
+
+        >>> cdf = df.rename_axis(columns='col')
+        >>> cdf
+        col      x   y
+        let num
+        a   1    0   0
+            2    1  10
+        b   1    2  20
+            2    3  30
+        c   1    4  40
+            2    5  50
+
+        >>> cdf.rename_axis(columns=str.upper)
+        COL      x   y
+        let num
+        a   1    0   0
+            2    1  10
+        b   1    2  20
+            2    3  30
+        c   1    4  40
+            2    5  50
+
+        """
+        axes, kwargs = self._construct_axes_from_arguments((), kwargs)
+        copy = kwargs.pop('copy', True)
+        inplace = kwargs.pop('inplace', False)
+        axis = kwargs.pop('axis', 0)
+        if axis is not None:
+            axis = self._get_axis_number(axis)
+
+        if kwargs:
+            raise TypeError('rename_axis() got an unexpected keyword '
+                            'argument "{0}"'.format(list(kwargs.keys())[0]))
+
         inplace = validate_bool_kwarg(inplace, 'inplace')
-        non_mapper = is_scalar(mapper) or (is_list_like(mapper) and not
-                                           is_dict_like(mapper))
-        if non_mapper:
-            return self._set_axis_name(mapper, axis=axis, inplace=inplace)
+
+        if (mapper is not None):
+            # Use v0.23 behavior if a scalar or list
+            non_mapper = is_scalar(mapper) or (is_list_like(mapper) and not
+                                               is_dict_like(mapper))
+            if non_mapper:
+                return self._set_axis_name(mapper, axis=axis, inplace=inplace)
+            else:
+                # Deprecated (v0.21) behavior is if mapper is specified,
+                # and not a list or scalar, then call rename
+                msg = ("Using 'rename_axis' to alter labels is deprecated. "
+                       "Use '.rename' instead")
+                warnings.warn(msg, FutureWarning, stacklevel=3)
+                axis = self._get_axis_name(axis)
+                d = {'copy': copy, 'inplace': inplace}
+                d[axis] = mapper
+                return self.rename(**d)
         else:
-            msg = ("Using 'rename_axis' to alter labels is deprecated. "
-                   "Use '.rename' instead")
-            warnings.warn(msg, FutureWarning, stacklevel=2)
-            axis = self._get_axis_name(axis)
-            d = {'copy': copy, 'inplace': inplace}
-            d[axis] = mapper
-            return self.rename(**d)
+            # Use new behavior.  Means that index and/or columns
+            # is specified
+            result = self if inplace else self.copy(deep=copy)
+
+            for axis in lrange(self._AXIS_LEN):
+                v = axes.get(self._AXIS_NAMES[axis])
+                if v is None:
+                    continue
+                non_mapper = is_scalar(v) or (is_list_like(v) and not
+                                              is_dict_like(v))
+                if non_mapper:
+                    newnames = v
+                else:
+                    f = com._get_rename_function(v)
+                    curnames = self._get_axis(axis).names
+                    newnames = [f(name) for name in curnames]
+                result._set_axis_name(newnames, axis=axis,
+                                      inplace=True)
+            if not inplace:
+                return result
 
     def _set_axis_name(self, name, axis=0, inplace=False):
         """


Test patch:
diff --git a/pandas/tests/frame/test_alter_axes.py b/pandas/tests/frame/test_alter_axes.py
--- a/pandas/tests/frame/test_alter_axes.py
+++ b/pandas/tests/frame/test_alter_axes.py
@@ -538,6 +538,52 @@ def test_rename_axis_warns(self):
             df['A'].rename_axis(id)
             assert 'rename' in str(w[0].message)
 
+    def test_rename_axis_mapper(self):
+        # GH 19978
+        mi = MultiIndex.from_product([['a', 'b', 'c'], [1, 2]],
+                                     names=['ll', 'nn'])
+        df = DataFrame({'x': [i for i in range(len(mi))],
+                        'y': [i * 10 for i in range(len(mi))]},
+                       index=mi)
+
+        # Test for rename of the Index object of columns
+        result = df.rename_axis('cols', axis=1)
+        tm.assert_index_equal(result.columns,
+                              Index(['x', 'y'], name='cols'))
+
+        # Test for rename of the Index object of columns using dict
+        result = result.rename_axis(columns={'cols': 'new'}, axis=1)
+        tm.assert_index_equal(result.columns,
+                              Index(['x', 'y'], name='new'))
+
+        # Test for renaming index using dict
+        result = df.rename_axis(index={'ll': 'foo'})
+        assert result.index.names == ['foo', 'nn']
+
+        # Test for renaming index using a function
+        result = df.rename_axis(index=str.upper, axis=0)
+        assert result.index.names == ['LL', 'NN']
+
+        # Test for renaming index providing complete list
+        result = df.rename_axis(index=['foo', 'goo'])
+        assert result.index.names == ['foo', 'goo']
+
+        # Test for changing index and columns at same time
+        sdf = df.reset_index().set_index('nn').drop(columns=['ll', 'y'])
+        result = sdf.rename_axis(index='foo', columns='meh')
+        assert result.index.name == 'foo'
+        assert result.columns.name == 'meh'
+
+        # Test different error cases
+        with tm.assert_raises_regex(TypeError, 'Must pass'):
+            df.rename_axis(index='wrong')
+
+        with tm.assert_raises_regex(ValueError, 'Length of names'):
+            df.rename_axis(index=['wrong'])
+
+        with tm.assert_raises_regex(TypeError, 'bogus'):
+            df.rename_axis(bogus=None)
+
     def test_rename_multiindex(self):
 
         tuples_index = [('foo1', 'bar1'), ('foo2', 'bar2')]
diff --git a/pandas/tests/io/test_pytables.py b/pandas/tests/io/test_pytables.py
--- a/pandas/tests/io/test_pytables.py
+++ b/pandas/tests/io/test_pytables.py
@@ -1345,8 +1345,8 @@ def test_append_with_strings(self):
             with catch_warnings(record=True):
                 simplefilter("ignore", FutureWarning)
                 wp = tm.makePanel()
-                wp2 = wp.rename_axis(
-                    {x: "%s_extra" % x for x in wp.minor_axis}, axis=2)
+                wp2 = wp.rename(
+                    minor_axis={x: "%s_extra" % x for x in wp.minor_axis})
 
                 def check_col(key, name, size):
                     assert getattr(store.get_storer(key)
diff --git a/pandas/tests/reshape/test_concat.py b/pandas/tests/reshape/test_concat.py
--- a/pandas/tests/reshape/test_concat.py
+++ b/pandas/tests/reshape/test_concat.py
@@ -1553,12 +1553,11 @@ def df():
         panel1 = make_panel()
         panel2 = make_panel()
 
-        panel2 = panel2.rename_axis({x: "%s_1" % x
-                                     for x in panel2.major_axis},
-                                    axis=1)
+        panel2 = panel2.rename(major_axis={x: "%s_1" % x
+                                           for x in panel2.major_axis})
 
-        panel3 = panel2.rename_axis(lambda x: '%s_1' % x, axis=1)
-        panel3 = panel3.rename_axis(lambda x: '%s_1' % x, axis=2)
+        panel3 = panel2.rename(major_axis=lambda x: '%s_1' % x)
+        panel3 = panel3.rename(minor_axis=lambda x: '%s_1' % x)
 
         # it works!
         concat([panel1, panel3], axis=1, verify_integrity=True, sort=sort)
diff --git a/pandas/tests/series/test_alter_axes.py b/pandas/tests/series/test_alter_axes.py
--- a/pandas/tests/series/test_alter_axes.py
+++ b/pandas/tests/series/test_alter_axes.py
@@ -226,6 +226,24 @@ def test_reorder_levels(self):
         expected = Series(np.arange(6), index=e_idx)
         tm.assert_series_equal(result, expected)
 
+    def test_rename_axis_mapper(self):
+        # GH 19978
+        mi = MultiIndex.from_product([['a', 'b', 'c'], [1, 2]],
+                                     names=['ll', 'nn'])
+        s = Series([i for i in range(len(mi))], index=mi)
+
+        result = s.rename_axis(index={'ll': 'foo'})
+        assert result.index.names == ['foo', 'nn']
+
+        result = s.rename_axis(index=str.upper, axis=0)
+        assert result.index.names == ['LL', 'NN']
+
+        result = s.rename_axis(index=['foo', 'goo'])
+        assert result.index.names == ['foo', 'goo']
+
+        with tm.assert_raises_regex(TypeError, 'unexpected'):
+            s.rename_axis(columns='wrong')
+
     def test_rename_axis_inplace(self, datetime_series):
         # GH 15704
         expected = datetime_series.rename_axis('foo')
diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py
--- a/pandas/tests/test_panel.py
+++ b/pandas/tests/test_panel.py
@@ -2110,16 +2110,16 @@ def test_repr_empty(self):
     def test_rename(self):
         mapper = {'ItemA': 'foo', 'ItemB': 'bar', 'ItemC': 'baz'}
 
-        renamed = self.panel.rename_axis(mapper, axis=0)
+        renamed = self.panel.rename(items=mapper)
         exp = Index(['foo', 'bar', 'baz'])
         tm.assert_index_equal(renamed.items, exp)
 
-        renamed = self.panel.rename_axis(str.lower, axis=2)
+        renamed = self.panel.rename(minor_axis=str.lower)
         exp = Index(['a', 'b', 'c', 'd'])
         tm.assert_index_equal(renamed.minor_axis, exp)
 
         # don't copy
-        renamed_nocopy = self.panel.rename_axis(mapper, axis=0, copy=False)
+        renamed_nocopy = self.panel.rename(items=mapper, copy=False)
         renamed_nocopy['foo'] = 3.
         assert (self.panel['ItemA'].values == 3).all()