diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 7c52cf6f450b2a..d7eb7ba4a2fc05 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -34,6 +34,7 @@ Other Enhancements - :func:`Series.to_dict` and :func:`DataFrame.to_dict` now support an ``into`` keyword which allows you to specify the ``collections.Mapping`` subclass that you would like returned. The default is ``dict``, which is backwards compatible. (:issue:`16122`) - :func:`RangeIndex.append` now returns a ``RangeIndex`` object when possible (:issue:`16212`) - :func:`Series.rename_axis` and :func:`DataFrame.rename_axis` with ``inplace=True`` now return ``None`` while renaming the axis inplace. (:issue:`15704`) +- :func:`Series.set_axis` now supports the ``inplace=`` parameter. (:issue:`14656`) - :func:`Series.to_pickle` and :func:`DataFrame.to_pickle` have gained a ``protocol`` parameter (:issue:`16252`). By default, this parameter is set to `HIGHEST_PROTOCOL `__ - :func:`api.types.infer_dtype` now infers decimals. (:issue:`15690`) - :func:`read_feather` has gained the ``nthreads`` parameter for multi-threaded operations (:issue:`16359`) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index f12592feaa4c36..a5f27d5df66f98 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -466,9 +466,70 @@ def _expand_axes(self, key): return new_axes - def set_axis(self, axis, labels): - """ public verson of axis assignment """ - setattr(self, self._get_axis_name(axis), labels) + _shared_docs['set_axis'] = """Assign desired index to given axis + + Parameters + ---------- + axis : int or string, default 0 + labels: list-like or Index + The values for the new index + inplace : boolean, default False + Whether to return a new %(klass)s. If True then value of copy is + ignored. + + WARNING: inplace=None currently falls back to to True, but + in a future version, will default to False. Use inplace=True + explicitly rather than relying on the default. + + Returns + ------- + renamed : %(klass)s (new object) if inplace=False, None otherwise + + See Also + -------- + pandas.NDFrame.rename + + Examples + -------- + >>> s = pd.Series([1, 2, 3]) + >>> s + 0 1 + 1 2 + 2 3 + dtype: int64 + >>> s.set_axis(0, ['a', 'b', 'c'], inplace=False) + a 1 + b 2 + c 3 + dtype: int64 + >>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) + >>> df.set_axis(0, ['a', 'b', 'c'], inplace=False) + A B + a 1 4 + b 2 5 + c 3 6 + >>> df.set_axis(1, ['I', 'II'], inplace=False) + I II + 0 1 4 + 1 2 5 + 2 3 6 + """ + + @Appender(_shared_docs['set_axis'] % dict(klass='NDFrame')) + def set_axis(self, axis=0, labels=None, inplace=None): + if inplace is None: + warnings.warn( + "set_axis currently defaults to operating inplace.\nThis " + "will change in a future version of pandas, use " + "inplace=True to avoid this warning.", + FutureWarning, stacklevel=2) + inplace = True + if inplace: + setattr(self, self._get_axis_name(axis), labels) + else: + obj = self.copy() + obj.set_axis(axis, labels, inplace=True) + return obj def _set_axis(self, axis, labels): self._data.set_axis(axis, labels) diff --git a/pandas/tests/frame/test_alter_axes.py b/pandas/tests/frame/test_alter_axes.py index 434c02b8eba2f3..f13f66faa2a45e 100644 --- a/pandas/tests/frame/test_alter_axes.py +++ b/pandas/tests/frame/test_alter_axes.py @@ -908,3 +908,37 @@ def test_set_reset_index(self): df = df.set_index('B') df = df.reset_index() + + def test_set_axis(self): + + df = DataFrame({'A': [1.1, 2.2, 3.3], + 'B': [5.0, 6.1, 7.2], + 'C': [4.4, 5.5, 6.6]}, + index=[2010, 2011, 2012]) + + expected = {0: df.copy(), + 1: df.copy()} + expected[0].index = list('abc') + expected[1].columns = list('abc') + expected['index'] = expected[0] + expected['columns'] = expected[1] + + for axis in expected: + # inplace=True + for inplace, warn in (None, FutureWarning), (True, None): + kwargs = {'inplace': inplace} + + result = df.copy() + with tm.assert_produces_warning(warn): + result.set_axis(axis, list('abc'), **kwargs) + tm.assert_frame_equal(result, expected[axis]) + + # GH14636 (inplace=False) + result = df.set_axis(axis, list('abc'), inplace=False) + tm.assert_frame_equal(expected[axis], result) + + # omitting the "axis=" parameter: + result = df.copy() + with tm.assert_produces_warning(warn): + result.set_axis(labels=list('abc'), **kwargs) + tm.assert_frame_equal(result, expected[0]) diff --git a/pandas/tests/series/test_alter_axes.py b/pandas/tests/series/test_alter_axes.py index d93f0326fd3b11..34cd5e3c41ad43 100644 --- a/pandas/tests/series/test_alter_axes.py +++ b/pandas/tests/series/test_alter_axes.py @@ -234,3 +234,29 @@ def test_rename_axis_inplace(self): assert no_return is None assert_series_equal(result, expected) + + def test_set_axis(self): + + s = Series(np.arange(4), index=[1, 3, 5, 7], dtype='int64') + + expected = s.copy() + expected.index = list('abcd') + + for axis in 0, 'index': + # inplace=True + for inplace, warn in (None, FutureWarning), (True, None): + result = s.copy() + kwargs = {'inplace': inplace} + with tm.assert_produces_warning(warn): + result.set_axis(0, list('abcd'), **kwargs) + tm.assert_series_equal(result, expected) + + # GH14636 (inplace=False) + result = s.set_axis(0, list('abcd'), inplace=False) + tm.assert_series_equal(expected, result) + + # omitting the "axis=" parameter: + result = s.copy() + with tm.assert_produces_warning(warn): + result.set_axis(labels=list('abcd'), **kwargs) + tm.assert_series_equal(result, expected)