diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index d654cf5715bdf..3768af266339d 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -681,6 +681,7 @@ Deprecations - Deprecated passing arguments as positional in :meth:`DataFrame.clip` and :meth:`Series.clip` (other than ``"upper"`` and ``"lower"``) (:issue:`41485`) - Deprecated special treatment of lists with first element a Categorical in the :class:`DataFrame` constructor; pass as ``pd.DataFrame({col: categorical, ...})`` instead (:issue:`38845`) - Deprecated passing arguments as positional (except for ``"method"``) in :meth:`DataFrame.interpolate` and :meth:`Series.interpolate` (:issue:`41485`) +- Deprecated passing arguments as positional (except for ``"levels"``) in :meth:`MultiIndex.set_levels` (:issue:`41485`) - Deprecated passing arguments as positional in :meth:`DataFrame.sort_index` and :meth:`Series.sort_index` (:issue:`41485`) - Deprecated passing arguments as positional in :meth:`DataFrame.drop_duplicates` (except for ``subset``), :meth:`Series.drop_duplicates`, :meth:`Index.drop_duplicates` and :meth:`MultiIndex.drop_duplicates`(:issue:`41485`) - Deprecated passing arguments (apart from ``value``) as positional in :meth:`DataFrame.fillna` and :meth:`Series.fillna` (:issue:`41485`) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 86d1503fe31c0..6a13ffa5a376b 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -804,6 +804,7 @@ def _set_levels( self._reset_cache() + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "levels"]) def set_levels( self, levels, level=None, inplace=None, verify_integrity: bool = True ): @@ -895,7 +896,7 @@ def set_levels( warnings.warn( "inplace is deprecated and will be removed in a future version.", FutureWarning, - stacklevel=2, + stacklevel=3, ) else: inplace = False diff --git a/pandas/tests/indexes/multi/test_get_set.py b/pandas/tests/indexes/multi/test_get_set.py index 0c561395788ad..9657e74c363b9 100644 --- a/pandas/tests/indexes/multi/test_get_set.py +++ b/pandas/tests/indexes/multi/test_get_set.py @@ -351,7 +351,7 @@ def test_set_levels_categorical(ordered): index = MultiIndex.from_arrays([list("xyzx"), [0, 1, 2, 3]]) cidx = CategoricalIndex(list("bac"), ordered=ordered) - result = index.set_levels(cidx, 0) + result = index.set_levels(cidx, level=0) expected = MultiIndex(levels=[cidx, [0, 1, 2, 3]], codes=index.codes) tm.assert_index_equal(result, expected) @@ -405,3 +405,30 @@ def test_set_levels_inplace_deprecated(idx, inplace): with tm.assert_produces_warning(FutureWarning): idx.set_levels(levels=new_level, level=1, inplace=inplace) + + +def test_set_levels_pos_args_deprecation(): + # https://github.com/pandas-dev/pandas/issues/41485 + idx = MultiIndex.from_tuples( + [ + (1, "one"), + (2, "one"), + (3, "one"), + ], + names=["foo", "bar"], + ) + msg = ( + r"In a future version of pandas all arguments of MultiIndex.set_levels except " + r"for the argument 'levels' will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = idx.set_levels(["a", "b", "c"], 0) + expected = MultiIndex.from_tuples( + [ + ("a", "one"), + ("b", "one"), + ("c", "one"), + ], + names=["foo", "bar"], + ) + tm.assert_index_equal(result, expected)