From 65acedc6a158910c80420e5d8343df32e0bcfb73 Mon Sep 17 00:00:00 2001 From: Luke Manley Date: Sun, 23 Oct 2022 07:55:42 -0400 Subject: [PATCH 1/4] enforce deprecation MultiIndex.is_lexsorted and MultiIndex.lexsort_depth --- doc/source/whatsnew/v2.0.0.rst | 1 + pandas/conftest.py | 1 - pandas/core/indexes/multi.py | 33 ++++++---------------- pandas/tests/indexes/multi/test_lexsort.py | 17 ----------- pandas/tests/indexes/multi/test_setops.py | 4 +-- 5 files changed, 10 insertions(+), 46 deletions(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 4ac737bb6b29a..342b223dca05c 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -156,6 +156,7 @@ Removal of prior version deprecations/changes - Remove arguments ``names`` and ``dtype`` from :meth:`Index.copy` and ``levels`` and ``codes`` from :meth:`MultiIndex.copy` (:issue:`35853`, :issue:`36685`) - Remove argument ``inplace`` from :meth:`MultiIndex.set_levels` and :meth:`MultiIndex.set_codes` (:issue:`35626`) - Disallow passing positional arguments to :meth:`MultiIndex.set_levels` and :meth:`MultiIndex.set_codes` (:issue:`41485`) +- Removed deprecated :meth:`MultiIndex.is_lexsorted` and :meth:`MultiIndex.lexsort_depth` (:issue:`38701`) - Removed argument ``try_cast`` from :meth:`DataFrame.mask`, :meth:`DataFrame.where`, :meth:`Series.mask` and :meth:`Series.where` (:issue:`38836`) - Disallow passing non-round floats to :class:`Timestamp` with ``unit="M"`` or ``unit="Y"`` (:issue:`47266`) - Removed deprecated :meth:`Timedelta.delta`, :meth:`Timedelta.is_populated`, and :attr:`Timedelta.freq` (:issue:`46430`, :issue:`46476`) diff --git a/pandas/conftest.py b/pandas/conftest.py index e8f982949677c..febd436c9f9bb 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -156,7 +156,6 @@ def pytest_collection_modifyitems(items, config) -> None: ("dtypes.common.is_categorical", "is_categorical is deprecated"), ("Categorical.replace", "Categorical.replace is deprecated"), ("Index.is_mixed", "Index.is_mixed is deprecated"), - ("MultiIndex._is_lexsorted", "MultiIndex.is_lexsorted is deprecated"), # Docstring divides by zero to show behavior difference ("missing.mask_zero_div_zero", "divide by zero encountered"), # Docstring demonstrates the call raises a warning diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 59a0179f93c10..761869d2b5954 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -1810,15 +1810,6 @@ def to_flat_index(self) -> Index: # type: ignore[override] """ return Index(self._values, tupleize_cols=False) - def is_lexsorted(self) -> bool: - warnings.warn( - "MultiIndex.is_lexsorted is deprecated as a public function, " - "users should use MultiIndex.is_monotonic_increasing instead.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return self._is_lexsorted() - def _is_lexsorted(self) -> bool: """ Return True if the codes are lexicographically sorted. @@ -1832,37 +1823,29 @@ def _is_lexsorted(self) -> bool: In the below examples, the first level of the MultiIndex is sorted because a>> pd.MultiIndex.from_arrays([['a', 'b', 'c'], ['d', 'e', 'f']]).is_lexsorted() + >>> pd.MultiIndex.from_arrays([['a', 'b', 'c'], + ... ['d', 'e', 'f']])._is_lexsorted() True - >>> pd.MultiIndex.from_arrays([['a', 'b', 'c'], ['d', 'f', 'e']]).is_lexsorted() + >>> pd.MultiIndex.from_arrays([['a', 'b', 'c'], + ... ['d', 'f', 'e']])._is_lexsorted() True In case there is a tie, the lexicographical sorting looks at the next level of the MultiIndex. - >>> pd.MultiIndex.from_arrays([[0, 1, 1], ['a', 'b', 'c']]).is_lexsorted() + >>> pd.MultiIndex.from_arrays([[0, 1, 1], ['a', 'b', 'c']])._is_lexsorted() True - >>> pd.MultiIndex.from_arrays([[0, 1, 1], ['a', 'c', 'b']]).is_lexsorted() + >>> pd.MultiIndex.from_arrays([[0, 1, 1], ['a', 'c', 'b']])._is_lexsorted() False >>> pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'], - ... ['aa', 'bb', 'aa', 'bb']]).is_lexsorted() + ... ['aa', 'bb', 'aa', 'bb']])._is_lexsorted() True >>> pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'], - ... ['bb', 'aa', 'aa', 'bb']]).is_lexsorted() + ... ['bb', 'aa', 'aa', 'bb']])._is_lexsorted() False """ return self._lexsort_depth == self.nlevels - @property - def lexsort_depth(self) -> int: - warnings.warn( - "MultiIndex.lexsort_depth is deprecated as a public function, " - "users should use MultiIndex.is_monotonic_increasing instead.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return self._lexsort_depth - @cache_readonly def _lexsort_depth(self) -> int: """ diff --git a/pandas/tests/indexes/multi/test_lexsort.py b/pandas/tests/indexes/multi/test_lexsort.py index 0aadbdb5c32da..fc16a4197a3a4 100644 --- a/pandas/tests/indexes/multi/test_lexsort.py +++ b/pandas/tests/indexes/multi/test_lexsort.py @@ -1,5 +1,4 @@ from pandas import MultiIndex -import pandas._testing as tm class TestIsLexsorted: @@ -22,14 +21,6 @@ def test_is_lexsorted(self): assert not index._is_lexsorted() assert index._lexsort_depth == 0 - def test_is_lexsorted_deprecation(self): - # GH 32259 - with tm.assert_produces_warning( - FutureWarning, - match="MultiIndex.is_lexsorted is deprecated as a public function", - ): - MultiIndex.from_arrays([["a", "b", "c"], ["d", "f", "e"]]).is_lexsorted() - class TestLexsortDepth: def test_lexsort_depth(self): @@ -53,11 +44,3 @@ def test_lexsort_depth(self): levels=levels, codes=[[0, 0, 1, 0, 1, 1], [0, 1, 0, 2, 2, 1]], sortorder=0 ) assert index._lexsort_depth == 0 - - def test_lexsort_depth_deprecation(self): - # GH 32259 - with tm.assert_produces_warning( - FutureWarning, - match="MultiIndex.lexsort_depth is deprecated as a public function", - ): - MultiIndex.from_arrays([["a", "b", "c"], ["d", "f", "e"]]).lexsort_depth diff --git a/pandas/tests/indexes/multi/test_setops.py b/pandas/tests/indexes/multi/test_setops.py index 61e602f4c41fe..eaa4e0a7b5256 100644 --- a/pandas/tests/indexes/multi/test_setops.py +++ b/pandas/tests/indexes/multi/test_setops.py @@ -683,9 +683,7 @@ def test_intersection_lexsort_depth(levels1, levels2, codes1, codes2, names): mi1 = MultiIndex(levels=levels1, codes=codes1, names=names) mi2 = MultiIndex(levels=levels2, codes=codes2, names=names) mi_int = mi1.intersection(mi2) - - with tm.assert_produces_warning(FutureWarning, match="MultiIndex.lexsort_depth"): - assert mi_int.lexsort_depth == 2 + assert mi_int._lexsort_depth == 2 @pytest.mark.parametrize("val", [pd.NA, 100]) From ae2f0adafb19350785dcf834d70304b0fd50f833 Mon Sep 17 00:00:00 2001 From: Luke Manley Date: Sun, 23 Oct 2022 10:45:17 -0400 Subject: [PATCH 2/4] add okexcept to 0.15.2.rst --- doc/source/whatsnew/v0.15.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.15.2.rst b/doc/source/whatsnew/v0.15.2.rst index 2dae76dd6b461..87c0646454e45 100644 --- a/doc/source/whatsnew/v0.15.2.rst +++ b/doc/source/whatsnew/v0.15.2.rst @@ -25,7 +25,7 @@ API changes a lexically sorted index will have a better performance. (:issue:`2646`) .. ipython:: python - :okwarning: + :okexcept: df = pd.DataFrame({'jim':[0, 0, 1, 1], 'joe':['x', 'x', 'z', 'y'], From 61afef3b8b53cab5fe921bc127aaeebbda6da30f Mon Sep 17 00:00:00 2001 From: Luke Manley Date: Sun, 23 Oct 2022 15:35:37 -0400 Subject: [PATCH 3/4] doc fix --- doc/source/whatsnew/v0.15.2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.15.2.rst b/doc/source/whatsnew/v0.15.2.rst index 87c0646454e45..fd4946c9765e1 100644 --- a/doc/source/whatsnew/v0.15.2.rst +++ b/doc/source/whatsnew/v0.15.2.rst @@ -26,6 +26,7 @@ API changes .. ipython:: python :okexcept: + :okwarning: df = pd.DataFrame({'jim':[0, 0, 1, 1], 'joe':['x', 'x', 'z', 'y'], From 97fac03b5546368026343fc8359515b166d70539 Mon Sep 17 00:00:00 2001 From: Luke Manley Date: Sun, 23 Oct 2022 15:36:50 -0400 Subject: [PATCH 4/4] doc fix --- doc/source/whatsnew/v2.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index cc2342063ff33..21e55b1f262dc 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -177,7 +177,7 @@ Removal of prior version deprecations/changes - Remove arguments ``names`` and ``dtype`` from :meth:`Index.copy` and ``levels`` and ``codes`` from :meth:`MultiIndex.copy` (:issue:`35853`, :issue:`36685`) - Remove argument ``inplace`` from :meth:`MultiIndex.set_levels` and :meth:`MultiIndex.set_codes` (:issue:`35626`) - Disallow passing positional arguments to :meth:`MultiIndex.set_levels` and :meth:`MultiIndex.set_codes` (:issue:`41485`) -- Removed deprecated :meth:`MultiIndex.is_lexsorted` and :meth:`MultiIndex.lexsort_depth` (:issue:`38701`) +- Removed :meth:`MultiIndex.is_lexsorted` and :meth:`MultiIndex.lexsort_depth` (:issue:`38701`) - Removed argument ``how`` from :meth:`PeriodIndex.astype`, use :meth:`PeriodIndex.to_timestamp` instead (:issue:`37982`) - Removed argument ``try_cast`` from :meth:`DataFrame.mask`, :meth:`DataFrame.where`, :meth:`Series.mask` and :meth:`Series.where` (:issue:`38836`) - Removed argument ``is_copy`` from :meth:`DataFrame.take` and :meth:`Series.take` (:issue:`30615`)