Skip to content

Commit 185ea60

Browse files
committed
ENH: provide "inplace" argument to set_axis()
closes #14636
1 parent 9e7666d commit 185ea60

File tree

4 files changed

+174
-3
lines changed

4 files changed

+174
-3
lines changed

doc/source/whatsnew/v0.21.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Other Enhancements
6666
- :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`)
6767
- :func:`RangeIndex.append` now returns a ``RangeIndex`` object when possible (:issue:`16212`)
6868
- :func:`Series.rename_axis` and :func:`DataFrame.rename_axis` with ``inplace=True`` now return ``None`` while renaming the axis inplace. (:issue:`15704`)
69+
- :func:`Series.set_axis` now supports the ``inplace`` parameter. (:issue:`14656`)
6970
- :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 <https://docs.python.org/3/library/pickle.html#data-stream-format>`__
7071
- :func:`api.types.infer_dtype` now infers decimals. (:issue:`15690`)
7172
- :func:`read_feather` has gained the ``nthreads`` parameter for multi-threaded operations (:issue:`16359`)

pandas/core/generic.py

+80-3
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,86 @@ def _expand_axes(self, key):
466466

467467
return new_axes
468468

469-
def set_axis(self, axis, labels):
470-
""" public verson of axis assignment """
471-
setattr(self, self._get_axis_name(axis), labels)
469+
_shared_docs['set_axis'] = """Assign desired index to given axis
470+
471+
Parameters
472+
----------
473+
labels: list-like or Index
474+
The values for the new index
475+
axis : int or string, default 0
476+
inplace : boolean, default None
477+
Whether to return a new %(klass)s instance.
478+
479+
WARNING: inplace=None currently falls back to to True, but
480+
in a future version, will default to False. Use inplace=True
481+
explicitly rather than relying on the default.
482+
483+
Returns
484+
-------
485+
renamed : %(klass)s or None
486+
New object if inplace=False, None otherwise.
487+
488+
See Also
489+
--------
490+
pandas.NDFrame.rename
491+
492+
Examples
493+
--------
494+
>>> s = pd.Series([1, 2, 3])
495+
>>> s
496+
0 1
497+
1 2
498+
2 3
499+
dtype: int64
500+
>>> s.set_axis(0, ['a', 'b', 'c'], inplace=False)
501+
a 1
502+
b 2
503+
c 3
504+
dtype: int64
505+
>>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
506+
>>> df.set_axis(0, ['a', 'b', 'c'], inplace=False)
507+
A B
508+
a 1 4
509+
b 2 5
510+
c 3 6
511+
>>> df.set_axis(1, ['I', 'II'], inplace=False)
512+
I II
513+
0 1 4
514+
1 2 5
515+
2 3 6
516+
>>> df.set_axis(1, ['i', 'ii'], inplace=True)
517+
>>> df
518+
i ii
519+
0 1 4
520+
1 2 5
521+
2 3 6
522+
523+
"""
524+
525+
@Appender(_shared_docs['set_axis'] % dict(klass='NDFrame'))
526+
def set_axis(self, labels, axis=0, inplace=None):
527+
if isinstance(labels, (int, str)):
528+
warnings.warn(
529+
"set_axis now takes \"labels\" as first argument, and "
530+
"\"axis\" as named parameter. The old form, with \"axis\" as "
531+
"first parameter and \"labels\" as second, is still supported "
532+
"but will be deprecated in a future version of pandas.",
533+
FutureWarning, stacklevel=2)
534+
labels, axis = axis, labels
535+
536+
if inplace is None:
537+
warnings.warn(
538+
"set_axis currently defaults to operating inplace.\nThis "
539+
"will change in a future version of pandas, use "
540+
"inplace=True to avoid this warning.",
541+
FutureWarning, stacklevel=2)
542+
inplace = True
543+
if inplace:
544+
setattr(self, self._get_axis_name(axis), labels)
545+
else:
546+
obj = self.copy()
547+
obj.set_axis(labels, axis=axis, inplace=True)
548+
return obj
472549

473550
def _set_axis(self, axis, labels):
474551
self._data.set_axis(axis, labels)

pandas/tests/frame/test_alter_axes.py

+54
Original file line numberDiff line numberDiff line change
@@ -908,3 +908,57 @@ def test_set_reset_index(self):
908908
df = df.set_index('B')
909909

910910
df = df.reset_index()
911+
912+
def test_set_axis_inplace(self):
913+
# GH14636
914+
df = DataFrame({'A': [1.1, 2.2, 3.3],
915+
'B': [5.0, 6.1, 7.2],
916+
'C': [4.4, 5.5, 6.6]},
917+
index=[2010, 2011, 2012])
918+
919+
expected = {0: df.copy(),
920+
1: df.copy()}
921+
expected[0].index = list('abc')
922+
expected[1].columns = list('abc')
923+
expected['index'] = expected[0]
924+
expected['columns'] = expected[1]
925+
926+
for axis in expected:
927+
# inplace=True
928+
# The FutureWarning comes from the fact that we would like to have
929+
# inplace default to False some day
930+
for inplace, warn in (None, FutureWarning), (True, None):
931+
kwargs = {'inplace': inplace}
932+
933+
result = df.copy()
934+
with tm.assert_produces_warning(warn):
935+
result.set_axis(list('abc'), axis=axis, **kwargs)
936+
tm.assert_frame_equal(result, expected[axis])
937+
938+
# inplace=False
939+
result = df.set_axis(list('abc'), axis=axis, inplace=False)
940+
tm.assert_frame_equal(expected[axis], result)
941+
942+
# omitting the "axis" parameter
943+
with tm.assert_produces_warning(None):
944+
result = df.set_axis(list('abc'), inplace=False)
945+
tm.assert_frame_equal(result, expected[0])
946+
947+
def test_set_axis_old_signature(self):
948+
df = DataFrame({'A': [1.1, 2.2, 3.3],
949+
'B': [5.0, 6.1, 7.2],
950+
'C': [4.4, 5.5, 6.6]},
951+
index=[2010, 2011, 2012])
952+
953+
expected = {0: df.copy(),
954+
1: df.copy()}
955+
expected[0].index = list('abc')
956+
expected[1].columns = list('abc')
957+
expected['index'] = expected[0]
958+
expected['columns'] = expected[1]
959+
960+
# old signature
961+
for axis in expected:
962+
with tm.assert_produces_warning(FutureWarning):
963+
result = df.set_axis(axis, list('abc'), inplace=False)
964+
tm.assert_frame_equal(result, expected[axis])

pandas/tests/series/test_alter_axes.py

+39
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,42 @@ def test_rename_axis_inplace(self):
234234

235235
assert no_return is None
236236
assert_series_equal(result, expected)
237+
238+
def test_set_axis_inplace(self):
239+
# GH14636
240+
241+
s = Series(np.arange(4), index=[1, 3, 5, 7], dtype='int64')
242+
243+
expected = s.copy()
244+
expected.index = list('abcd')
245+
246+
for axis in 0, 'index':
247+
# inplace=True
248+
# The FutureWarning comes from the fact that we would like to have
249+
# inplace default to False some day
250+
for inplace, warn in (None, FutureWarning), (True, None):
251+
result = s.copy()
252+
kwargs = {'inplace': inplace}
253+
with tm.assert_produces_warning(warn):
254+
result.set_axis(list('abcd'), axis=axis, **kwargs)
255+
tm.assert_series_equal(result, expected)
256+
257+
# inplace=False
258+
result = s.set_axis(list('abcd'), axis=0, inplace=False)
259+
tm.assert_series_equal(expected, result)
260+
261+
# omitting the "axis" parameter
262+
with tm.assert_produces_warning(None):
263+
result = s.set_axis(list('abcd'), inplace=False)
264+
tm.assert_series_equal(result, expected)
265+
266+
def test_set_axis_old_signature(self):
267+
s = Series(np.arange(4), index=[1, 3, 5, 7], dtype='int64')
268+
269+
expected = s.copy()
270+
expected.index = list('abcd')
271+
272+
for axis in 0, 'index':
273+
with tm.assert_produces_warning(FutureWarning):
274+
result = s.set_axis(0, list('abcd'), inplace=False)
275+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)