Skip to content

Commit f03c9fb

Browse files
jbrockmendelnoatamir
authored andcommitted
DEPR: set_axis inplace keyword (pandas-dev#48130)
* ENH: copy keyword to set_axis * GH ref * fix test * fix test * troubleshoot mypy * mypy fixup * test inplace=True/copy=False case * DEPR: inplace keyword in set_axis * GH ref
1 parent 5b44c8f commit f03c9fb

File tree

7 files changed

+62
-31
lines changed

7 files changed

+62
-31
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ Other Deprecations
841841
- Deprecated the ``inplace`` keyword in :meth:`Categorical.set_ordered`, :meth:`Categorical.as_ordered`, and :meth:`Categorical.as_unordered` (:issue:`37643`)
842842
- Deprecated setting a categorical's categories with ``cat.categories = ['a', 'b', 'c']``, use :meth:`Categorical.rename_categories` instead (:issue:`37643`)
843843
- Deprecated unused arguments ``encoding`` and ``verbose`` in :meth:`Series.to_excel` and :meth:`DataFrame.to_excel` (:issue:`47912`)
844+
- Deprecated the ``inplace`` keyword in :meth:`DataFrame.set_axis` and :meth:`Series.set_axis`, use ``obj = obj.set_axis(..., copy=False)`` instead (:issue:`48130`)
844845
- Deprecated producing a single element when iterating over a :class:`DataFrameGroupBy` or a :class:`SeriesGroupBy` that has been grouped by a list of length 1; A tuple of length one will be returned instead (:issue:`42795`)
845846
- Fixed up warning message of deprecation of :meth:`MultiIndex.lesort_depth` as public method, as the message previously referred to :meth:`MultiIndex.is_lexsorted` instead (:issue:`38701`)
846847
- Deprecated the ``inplace`` keyword in :meth:`DataFrame.set_index`, use ``df = df.set_index(..., copy=False)`` instead (:issue:`48115`)

pandas/core/frame.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -5061,7 +5061,7 @@ def set_axis(
50615061
labels,
50625062
*,
50635063
axis: Axis = ...,
5064-
inplace: Literal[False] = ...,
5064+
inplace: Literal[False] | lib.NoDefault = ...,
50655065
copy: bool | lib.NoDefault = ...,
50665066
) -> DataFrame:
50675067
...
@@ -5083,7 +5083,7 @@ def set_axis(
50835083
labels,
50845084
*,
50855085
axis: Axis = ...,
5086-
inplace: bool = ...,
5086+
inplace: bool | lib.NoDefault = ...,
50875087
copy: bool | lib.NoDefault = ...,
50885088
) -> DataFrame | None:
50895089
...
@@ -5112,10 +5112,9 @@ def set_axis(
51125112
1 2 5
51135113
2 3 6
51145114
5115-
Now, update the labels inplace.
5115+
Now, update the labels without copying the underlying data.
51165116
5117-
>>> df.set_axis(['i', 'ii'], axis='columns', inplace=True)
5118-
>>> df
5117+
>>> df.set_axis(['i', 'ii'], axis='columns', copy=False)
51195118
i ii
51205119
0 1 4
51215120
1 2 5
@@ -5133,7 +5132,7 @@ def set_axis(
51335132
self,
51345133
labels,
51355134
axis: Axis = 0,
5136-
inplace: bool = False,
5135+
inplace: bool | lib.NoDefault = lib.no_default,
51375136
*,
51385137
copy: bool | lib.NoDefault = lib.no_default,
51395138
):

pandas/core/generic.py

+26-11
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ def set_axis(
715715
labels,
716716
*,
717717
axis: Axis = ...,
718-
inplace: Literal[False] = ...,
718+
inplace: Literal[False] | lib.NoDefault = ...,
719719
copy: bool_t | lib.NoDefault = ...,
720720
) -> NDFrameT:
721721
...
@@ -737,7 +737,7 @@ def set_axis(
737737
labels,
738738
*,
739739
axis: Axis = ...,
740-
inplace: bool_t = ...,
740+
inplace: bool_t | lib.NoDefault = ...,
741741
copy: bool_t | lib.NoDefault = ...,
742742
) -> NDFrameT | None:
743743
...
@@ -747,7 +747,7 @@ def set_axis(
747747
self: NDFrameT,
748748
labels,
749749
axis: Axis = 0,
750-
inplace: bool_t = False,
750+
inplace: bool_t | lib.NoDefault = lib.no_default,
751751
*,
752752
copy: bool_t | lib.NoDefault = lib.no_default,
753753
) -> NDFrameT | None:
@@ -769,6 +769,8 @@ def set_axis(
769769
inplace : bool, default False
770770
Whether to return a new %(klass)s instance.
771771
772+
.. deprecated:: 1.5.0
773+
772774
copy : bool, default True
773775
Whether to make a copy of the underlying data.
774776
@@ -783,6 +785,17 @@ def set_axis(
783785
--------
784786
%(klass)s.rename_axis : Alter the name of the index%(see_also_sub)s.
785787
"""
788+
if inplace is not lib.no_default:
789+
warnings.warn(
790+
f"{type(self).__name__}.set_axis 'inplace' keyword is deprecated "
791+
"and will be removed in a future version. Use "
792+
"`obj = obj.set_axis(..., copy=False)` instead",
793+
FutureWarning,
794+
stacklevel=find_stack_level(inspect.currentframe()),
795+
)
796+
else:
797+
inplace = False
798+
786799
if inplace:
787800
if copy is True:
788801
raise ValueError("Cannot specify both inplace=True and copy=True")
@@ -795,14 +808,13 @@ def set_axis(
795808

796809
@final
797810
def _set_axis_nocheck(self, labels, axis: Axis, inplace: bool_t, copy: bool_t):
798-
# NDFrame.rename with inplace=False calls set_axis(inplace=True) on a copy.
799811
if inplace:
800812
setattr(self, self._get_axis_name(axis), labels)
801813
else:
802814
# With copy=False, we create a new object but don't copy the
803815
# underlying data.
804816
obj = self.copy(deep=copy)
805-
obj.set_axis(labels, axis=axis, inplace=True)
817+
setattr(obj, obj._get_axis_name(axis), labels)
806818
return obj
807819

808820
def _set_axis(self, axis: int, labels: AnyArrayLike | list) -> None:
@@ -904,7 +916,7 @@ def droplevel(self: NDFrameT, level: IndexLabel, axis: Axis = 0) -> NDFrameT:
904916
"""
905917
labels = self._get_axis(axis)
906918
new_labels = labels.droplevel(level)
907-
return self.set_axis(new_labels, axis=axis, inplace=False)
919+
return self.set_axis(new_labels, axis=axis)
908920

909921
def pop(self, item: Hashable) -> Series | Any:
910922
result = self[item]
@@ -1363,7 +1375,11 @@ def _set_axis_name(self, name, axis=0, inplace=False):
13631375

13641376
inplace = validate_bool_kwarg(inplace, "inplace")
13651377
renamed = self if inplace else self.copy()
1366-
renamed.set_axis(idx, axis=axis, inplace=True)
1378+
if axis == 0:
1379+
renamed.index = idx
1380+
else:
1381+
renamed.columns = idx
1382+
13671383
if not inplace:
13681384
return renamed
13691385

@@ -10205,8 +10221,7 @@ def slice_shift(self: NDFrameT, periods: int = 1, axis=0) -> NDFrameT:
1020510221

1020610222
new_obj = self._slice(vslicer, axis=axis)
1020710223
shifted_axis = self._get_axis(axis)[islicer]
10208-
new_obj.set_axis(shifted_axis, axis=axis, inplace=True)
10209-
10224+
new_obj = new_obj.set_axis(shifted_axis, axis=axis, copy=False)
1021010225
return new_obj.__finalize__(self, method="slice_shift")
1021110226

1021210227
@final
@@ -10465,7 +10480,7 @@ def _tz_convert(ax, tz):
1046510480
ax = _tz_convert(ax, tz)
1046610481

1046710482
result = self.copy(deep=copy)
10468-
result = result.set_axis(ax, axis=axis, inplace=False)
10483+
result = result.set_axis(ax, axis=axis, copy=False)
1046910484
return result.__finalize__(self, method="tz_convert")
1047010485

1047110486
@final
@@ -10635,7 +10650,7 @@ def _tz_localize(ax, tz, ambiguous, nonexistent):
1063510650
ax = _tz_localize(ax, tz, ambiguous, nonexistent)
1063610651

1063710652
result = self.copy(deep=copy)
10638-
result = result.set_axis(ax, axis=axis, inplace=False)
10653+
result = result.set_axis(ax, axis=axis, copy=False)
1063910654
return result.__finalize__(self, method="tz_localize")
1064010655

1064110656
# ----------------------------------------------------------------------

pandas/core/groupby/groupby.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1200,21 +1200,22 @@ def _set_result_index_ordered(
12001200
# set the result index on the passed values object and
12011201
# return the new object, xref 8046
12021202

1203+
obj_axis = self.obj._get_axis(self.axis)
1204+
12031205
if self.grouper.is_monotonic and not self.grouper.has_dropped_na:
12041206
# shortcut if we have an already ordered grouper
1205-
result.set_axis(self.obj._get_axis(self.axis), axis=self.axis, inplace=True)
1207+
result = result.set_axis(obj_axis, axis=self.axis, copy=False)
12061208
return result
12071209

12081210
# row order is scrambled => sort the rows by position in original index
12091211
original_positions = Index(self.grouper.result_ilocs())
1210-
result.set_axis(original_positions, axis=self.axis, inplace=True)
1212+
result = result.set_axis(original_positions, axis=self.axis, copy=False)
12111213
result = result.sort_index(axis=self.axis)
1212-
obj_axis = self.obj._get_axis(self.axis)
12131214
if self.grouper.has_dropped_na:
12141215
# Add back in any missing rows due to dropna - index here is integral
12151216
# with values referring to the row of the input so can use RangeIndex
12161217
result = result.reindex(RangeIndex(len(obj_axis)), axis=self.axis)
1217-
result.set_axis(obj_axis, axis=self.axis, inplace=True)
1218+
result = result.set_axis(obj_axis, axis=self.axis, copy=False)
12181219

12191220
return result
12201221

pandas/core/series.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4980,7 +4980,7 @@ def set_axis(
49804980
labels,
49814981
*,
49824982
axis: Axis = ...,
4983-
inplace: Literal[False] = ...,
4983+
inplace: Literal[False] | lib.NoDefault = ...,
49844984
copy: bool | lib.NoDefault = ...,
49854985
) -> Series:
49864986
...
@@ -5002,7 +5002,7 @@ def set_axis(
50025002
labels,
50035003
*,
50045004
axis: Axis = ...,
5005-
inplace: bool = ...,
5005+
inplace: bool | lib.NoDefault = ...,
50065006
copy: bool | lib.NoDefault = ...,
50075007
) -> Series | None:
50085008
...
@@ -5038,7 +5038,7 @@ def set_axis( # type: ignore[override]
50385038
self,
50395039
labels,
50405040
axis: Axis = 0,
5041-
inplace: bool = False,
5041+
inplace: bool | lib.NoDefault = lib.no_default,
50425042
copy: bool | lib.NoDefault = lib.no_default,
50435043
) -> Series | None:
50445044
return super().set_axis(labels, axis=axis, inplace=inplace, copy=copy)

pandas/tests/frame/methods/test_set_axis.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ def test_set_axis(self, obj):
2121
expected.index = new_index
2222

2323
# inplace=False
24-
result = obj.set_axis(new_index, axis=0, inplace=False)
24+
msg = "set_axis 'inplace' keyword is deprecated"
25+
with tm.assert_produces_warning(FutureWarning, match=msg):
26+
result = obj.set_axis(new_index, axis=0, inplace=False)
2527
tm.assert_equal(expected, result)
2628

2729
def test_set_axis_copy(self, obj):
@@ -35,7 +37,8 @@ def test_set_axis_copy(self, obj):
3537
with pytest.raises(
3638
ValueError, match="Cannot specify both inplace=True and copy=True"
3739
):
38-
obj.set_axis(new_index, axis=0, inplace=True, copy=True)
40+
with tm.assert_produces_warning(FutureWarning):
41+
obj.set_axis(new_index, axis=0, inplace=True, copy=True)
3942

4043
result = obj.set_axis(new_index, axis=0, copy=True)
4144
tm.assert_equal(expected, result)
@@ -75,7 +78,8 @@ def test_set_axis_copy(self, obj):
7578
)
7679

7780
# Do this last since it alters obj inplace
78-
res = obj.set_axis(new_index, inplace=True, copy=False)
81+
with tm.assert_produces_warning(FutureWarning):
82+
res = obj.set_axis(new_index, inplace=True, copy=False)
7983
assert res is None
8084
tm.assert_equal(expected, obj)
8185
# check we did NOT make a copy
@@ -103,7 +107,8 @@ def test_set_axis_inplace_axis(self, axis, obj):
103107
expected.columns = new_index
104108

105109
result = obj.copy()
106-
result.set_axis(new_index, axis=axis, inplace=True)
110+
with tm.assert_produces_warning(FutureWarning):
111+
result.set_axis(new_index, axis=axis, inplace=True)
107112
tm.assert_equal(result, expected)
108113

109114
def test_set_axis_unnamed_kwarg_warns(self, obj):
@@ -113,7 +118,9 @@ def test_set_axis_unnamed_kwarg_warns(self, obj):
113118
expected = obj.copy()
114119
expected.index = new_index
115120

116-
with tm.assert_produces_warning(None):
121+
with tm.assert_produces_warning(
122+
FutureWarning, match="set_axis 'inplace' keyword"
123+
):
117124
result = obj.set_axis(new_index, inplace=False)
118125
tm.assert_equal(result, expected)
119126

pandas/tests/generic/test_duplicate_labels.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,19 @@ def test_inplace_raises(method, frame_only):
429429
s.flags.allows_duplicate_labels = False
430430
msg = "Cannot specify"
431431

432+
warn_msg = "Series.set_axis 'inplace' keyword"
433+
if "set_axis" in str(method):
434+
warn = FutureWarning
435+
else:
436+
warn = None
437+
432438
with pytest.raises(ValueError, match=msg):
433-
method(df)
439+
with tm.assert_produces_warning(warn, match=warn_msg):
440+
method(df)
434441
if not frame_only:
435442
with pytest.raises(ValueError, match=msg):
436-
method(s)
443+
with tm.assert_produces_warning(warn, match=warn_msg):
444+
method(s)
437445

438446

439447
def test_pickle():

0 commit comments

Comments
 (0)