Skip to content

Commit bdbdab1

Browse files
authored
ENH: Add na_position support to midx.sort_values (#51651)
1 parent 7389f03 commit bdbdab1

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

doc/source/whatsnew/v2.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ enhancement2
2828

2929
Other enhancements
3030
^^^^^^^^^^^^^^^^^^
31+
- :meth:`MultiIndex.sort_values` now supports ``na_position`` (:issue:`51612`)
3132
- :meth:`MultiIndex.sortlevel` and :meth:`Index.sortlevel` gained a new keyword ``na_position`` (:issue:`51612`)
3233
- Improve error message when setting :class:`DataFrame` with wrong number of columns through :meth:`DataFrame.isetitem` (:issue:`51701`)
3334
- Let :meth:`DataFrame.to_feather` accept a non-default :class:`Index` and non-string column names (:issue:`51787`)

pandas/core/indexes/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5600,7 +5600,7 @@ def sort_values(
56005600
items=idx, ascending=ascending, na_position=na_position, key=key
56015601
)
56025602
else:
5603-
_as = idx.argsort()
5603+
_as = idx.argsort(na_position=na_position)
56045604
if not ascending:
56055605
_as = _as[::-1]
56065606

pandas/core/indexes/multi.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -2132,11 +2132,15 @@ def append(self, other):
21322132
except (TypeError, IndexError):
21332133
return Index(new_tuples)
21342134

2135-
def argsort(self, *args, **kwargs) -> npt.NDArray[np.intp]:
2135+
def argsort(
2136+
self, *args, na_position: str = "last", **kwargs
2137+
) -> npt.NDArray[np.intp]:
21362138
if len(args) == 0 and len(kwargs) == 0:
21372139
# lexsort is significantly faster than self._values.argsort()
21382140
target = self._sort_levels_monotonic(raise_if_incomparable=True)
2139-
return lexsort_indexer(target._get_codes_for_sorting())
2141+
return lexsort_indexer(
2142+
target._get_codes_for_sorting(), na_position=na_position
2143+
)
21402144
return self._values.argsort(*args, **kwargs)
21412145

21422146
@Appender(_index_shared_docs["repeat"] % _index_doc_kwargs)

pandas/tests/indexes/multi/test_sorting.py

+25
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Index,
1515
MultiIndex,
1616
RangeIndex,
17+
Series,
1718
Timestamp,
1819
)
1920
import pandas._testing as tm
@@ -311,3 +312,27 @@ def test_sort_values_incomparable():
311312
match = "'<' not supported between instances of 'Timestamp' and 'int'"
312313
with pytest.raises(TypeError, match=match):
313314
mi.sort_values()
315+
316+
317+
@pytest.mark.parametrize("na_position", ["first", "last"])
318+
@pytest.mark.parametrize("dtype", ["float64", "Int64", "Float64"])
319+
def test_sort_values_with_na_na_position(dtype, na_position):
320+
# 51612
321+
arrays = [
322+
Series([1, 1, 2], dtype=dtype),
323+
Series([1, None, 3], dtype=dtype),
324+
]
325+
index = MultiIndex.from_arrays(arrays)
326+
result = index.sort_values(na_position=na_position)
327+
if na_position == "first":
328+
arrays = [
329+
Series([1, 1, 2], dtype=dtype),
330+
Series([None, 1, 3], dtype=dtype),
331+
]
332+
else:
333+
arrays = [
334+
Series([1, 1, 2], dtype=dtype),
335+
Series([1, None, 3], dtype=dtype),
336+
]
337+
expected = MultiIndex.from_arrays(arrays)
338+
tm.assert_index_equal(result, expected)

0 commit comments

Comments
 (0)