diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index dd63ea94d5211..a576e0090747a 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2226,9 +2226,12 @@ def append(self, other): def argsort(self, *args, **kwargs) -> npt.NDArray[np.intp]: if len(args) == 0 and len(kwargs) == 0: - # np.lexsort is significantly faster than self._values.argsort() - values = [self._get_level_values(i) for i in reversed(range(self.nlevels))] - return np.lexsort(values) + if not any(-1 in code for code in self.codes): + # np.lexsort is significantly faster than self._values.argsort() + values = [ + self._get_level_values(i) for i in reversed(range(self.nlevels)) + ] + return np.lexsort(values) return self._values.argsort(*args, **kwargs) @Appender(_index_shared_docs["repeat"] % _index_doc_kwargs) diff --git a/pandas/tests/indexes/multi/test_sorting.py b/pandas/tests/indexes/multi/test_sorting.py index 6fd1781beeda4..0512daae694ce 100644 --- a/pandas/tests/indexes/multi/test_sorting.py +++ b/pandas/tests/indexes/multi/test_sorting.py @@ -280,3 +280,13 @@ def test_remove_unused_levels_with_nan(): result = idx.levels expected = FrozenList([["a", np.nan], [4]]) assert str(result) == str(expected) + + +def test_sort_values_nan(): + # GH# + midx = MultiIndex(levels=[["A", "B", "C"], ["D"]], codes=[[1, 0, 2], [-1, -1, 0]]) + result = midx.sort_values() + expected = MultiIndex( + levels=[["A", "B", "C"], ["D"]], codes=[[0, 1, 2], [-1, -1, 0]] + ) + tm.assert_index_equal(result, expected)