diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index a5cb716317689..d8b8f620a1d62 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -963,7 +963,7 @@ Other .. ***DO NOT USE THIS SECTION*** -- +- Bug in :func:`.assert_index_equal` with ``names=True`` and ``check_order=False`` not checking names (:issue:`47328`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 2029a7665d57a..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), dtype=left.dtype) - right = Index(safe_sort(right), dtype=right.dtype) + 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..634187a317baf 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,34 @@ 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) + except TypeError: + pass + else: + 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, dtype=index.dtype) + + 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 e3461e62b4eda..1fa7b979070a7 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])