From b4043d0c1e922ca4c9ee35be40989b06a8438eed Mon Sep 17 00:00:00 2001 From: phofl Date: Mon, 13 Jun 2022 11:45:45 +0200 Subject: [PATCH 1/4] BUG: assert_index_equal ignoring names when check_order is false --- doc/source/whatsnew/v1.5.0.rst | 2 +- pandas/_testing/asserters.py | 10 ++--- pandas/core/indexes/api.py | 41 +++++++++++++++----- pandas/tests/util/test_assert_index_equal.py | 8 ++++ 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 55bfb044fb31d..ed852a895645d 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -935,7 +935,7 @@ Other .. ***DO NOT USE THIS SECTION*** -- +- Bug in :func:`.assert_index_equal` with ``names=True`` and ``check_order=False`` not checking names not (:issue:`47328`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 7170089581f69..90ee600c1967d 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -45,10 +45,7 @@ Series, TimedeltaIndex, ) -from pandas.core.algorithms import ( - safe_sort, - take_nd, -) +from pandas.core.algorithms import take_nd from pandas.core.arrays import ( DatetimeArray, ExtensionArray, @@ -58,6 +55,7 @@ ) from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin from pandas.core.arrays.string_ import StringDtype +from pandas.core.indexes.api import safe_sort_index from pandas.io.formats.printing import pprint_thing @@ -367,8 +365,8 @@ def _get_ilevel_values(index, level): # If order doesn't matter then sort the index entries if not check_order: - left = Index(safe_sort(left)) - right = Index(safe_sort(right)) + left = safe_sort_index(left) + right = safe_sort_index(right) # MultiIndex special comparison for little-friendly error messages if left.nlevels > 1: diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index 1e740132e3464..a7e04397e64ac 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -70,6 +70,7 @@ "get_unanimous_names", "all_indexes_same", "default_index", + "safe_sort_index", ] @@ -157,16 +158,7 @@ def _get_combined_index( index = ensure_index(index) if sort: - try: - array_sorted = safe_sort(index) - array_sorted = cast(np.ndarray, array_sorted) - if isinstance(index, MultiIndex): - index = MultiIndex.from_tuples(array_sorted, names=index.names) - else: - index = Index(array_sorted, name=index.name) - except TypeError: - pass - + index = safe_sort_index(index) # GH 29879 if copy: index = index.copy() @@ -174,6 +166,35 @@ def _get_combined_index( return index +def safe_sort_index(index: Index) -> Index: + """ + Returns the sorted index + + We keep the dtypes and the name attributes. + + Parameters + ---------- + index : an Index + + Returns + ------- + Index + """ + try: + array_sorted = safe_sort(index) + array_sorted = cast(np.ndarray, array_sorted) + if isinstance(index, MultiIndex): + index = MultiIndex.from_tuples( + array_sorted, names=index.names, dtypes=index.dtypes + ) + else: + index = Index(array_sorted, name=index.name, dtype=index.dtype) + except TypeError: + pass + + return index + + def union_indexes(indexes, sort: bool | None = True) -> Index: """ Return the union of indexes. diff --git a/pandas/tests/util/test_assert_index_equal.py b/pandas/tests/util/test_assert_index_equal.py index 8211b52fed650..a0bf37e9e1bac 100644 --- a/pandas/tests/util/test_assert_index_equal.py +++ b/pandas/tests/util/test_assert_index_equal.py @@ -238,6 +238,14 @@ def test_index_equal_range_categories(check_categorical, exact): ) +def test_assert_index_equal_different_names_check_order_false(): + # GH#47328 + idx1 = Index([1, 3], name="a") + idx2 = Index([3, 1], name="b") + with pytest.raises(AssertionError, match='"names" are different'): + tm.assert_index_equal(idx1, idx2, check_order=False, check_names=True) + + def test_assert_index_equal_mixed_dtype(): # GH#39168 idx = Index(["foo", "bar", 42]) From ff66a6ed8e42a0a7cd7ecbeb5568c80c8fedd0bb Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Mon, 13 Jun 2022 12:09:21 +0200 Subject: [PATCH 2/4] Update doc/source/whatsnew/v1.5.0.rst Co-authored-by: Simon Hawkins --- doc/source/whatsnew/v1.5.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index ed852a895645d..1938567fd2e35 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -935,7 +935,7 @@ Other .. ***DO NOT USE THIS SECTION*** -- Bug in :func:`.assert_index_equal` with ``names=True`` and ``check_order=False`` not checking names not (:issue:`47328`) +- Bug in :func:`.assert_index_equal` with ``names=True`` and ``check_order=False`` not checking names (:issue:`47328`) - .. --------------------------------------------------------------------------- From 8e75e3415b9cf65b0207fb7c51fcc2ef0343d2b3 Mon Sep 17 00:00:00 2001 From: phofl Date: Mon, 13 Jun 2022 12:48:06 +0200 Subject: [PATCH 3/4] Move index creation to else block --- pandas/core/indexes/api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index a7e04397e64ac..c824f5bde21d6 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -182,6 +182,9 @@ def safe_sort_index(index: Index) -> Index: """ try: array_sorted = safe_sort(index) + except TypeError: + pass + else: array_sorted = cast(np.ndarray, array_sorted) if isinstance(index, MultiIndex): index = MultiIndex.from_tuples( @@ -189,8 +192,6 @@ def safe_sort_index(index: Index) -> Index: ) else: index = Index(array_sorted, name=index.name, dtype=index.dtype) - except TypeError: - pass return index From fa08a582aadea79ed4f6474962f9b62673e092d5 Mon Sep 17 00:00:00 2001 From: phofl Date: Mon, 13 Jun 2022 13:20:33 +0200 Subject: [PATCH 4/4] Remove dtypes --- pandas/core/indexes/api.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index c824f5bde21d6..634187a317baf 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -187,9 +187,7 @@ def safe_sort_index(index: Index) -> Index: else: array_sorted = cast(np.ndarray, array_sorted) if isinstance(index, MultiIndex): - index = MultiIndex.from_tuples( - array_sorted, names=index.names, dtypes=index.dtypes - ) + index = MultiIndex.from_tuples(array_sorted, names=index.names) else: index = Index(array_sorted, name=index.name, dtype=index.dtype)