diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index bd5cf43e19e9f..918d96cd03112 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -561,7 +561,7 @@ def argsort( ascending : bool, default True Whether the indices should result in an ascending or descending sort. - kind : {'quicksort', 'mergesort', 'heapsort'}, optional + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional Sorting algorithm. *args, **kwargs: Passed through to :func:`numpy.argsort`. diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 1bb5556663c29..0940920bb3dbe 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -1484,7 +1484,7 @@ def argsort(self, ascending=True, kind="quicksort", **kwargs): ascending : bool, default True Whether the indices should result in an ascending or descending sort. - kind : {'quicksort', 'mergesort', 'heapsort'}, optional + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional Sorting algorithm. **kwargs: passed through to :func:`numpy.argsort`. diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 7f295a73a82e6..cc89823cd7817 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -5526,9 +5526,9 @@ def sort_index( sort direction can be controlled for each level individually. inplace : bool, default False If True, perform operation in-place. - kind : {'quicksort', 'mergesort', 'heapsort'}, default 'quicksort' - Choice of sorting algorithm. See also ndarray.np.sort for more - information. `mergesort` is the only stable algorithm. For + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, default 'quicksort' + Choice of sorting algorithm. See also :func:`numpy.sort` for more + information. `mergesort` and `stable` are the only stable algorithms. For DataFrames, this option is only applied when sorting on a single column or label. na_position : {'first', 'last'}, default 'last' diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 4b0d524782924..a7dfdb3cfbd97 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -4383,11 +4383,11 @@ def sort_values( the by. inplace : bool, default False If True, perform operation in-place. - kind : {'quicksort', 'mergesort', 'heapsort'}, default 'quicksort' - Choice of sorting algorithm. See also ndarray.np.sort for more - information. `mergesort` is the only stable algorithm. For - DataFrames, if sorting by multiple columns or labels, this - argument is ignored, defaulting to a stable sorting algorithm. + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, default 'quicksort' + Choice of sorting algorithm. See also :func:`numpy.sort` for more + information. `mergesort` and `stable` are the only stable algorithms. For + DataFrames, this option is only applied when sorting on a single + column or label. na_position : {'first', 'last'}, default 'last' Puts NaNs at the beginning if `first`; `last` puts NaNs at the end. diff --git a/pandas/core/series.py b/pandas/core/series.py index d4ae5c2245b5b..cb753e887b0f8 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -3066,9 +3066,9 @@ def sort_values( If True, sort values in ascending order, otherwise descending. inplace : bool, default False If True, perform operation in-place. - kind : {'quicksort', 'mergesort' or 'heapsort'}, default 'quicksort' + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, default 'quicksort' Choice of sorting algorithm. See also :func:`numpy.sort` for more - information. 'mergesort' is the only stable algorithm. + information. 'mergesort' and 'stable' are the only stable algorithms. na_position : {'first' or 'last'}, default 'last' Argument 'first' puts NaNs at the beginning, 'last' puts NaNs at the end. @@ -3279,9 +3279,9 @@ def sort_index( sort direction can be controlled for each level individually. inplace : bool, default False If True, perform operation in-place. - kind : {'quicksort', 'mergesort', 'heapsort'}, default 'quicksort' + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, default 'quicksort' Choice of sorting algorithm. See also :func:`numpy.sort` for more - information. 'mergesort' is the only stable algorithm. For + information. 'mergesort' and 'stable' are the only stable algorithms. For DataFrames, this option is only applied when sorting on a single column or label. na_position : {'first', 'last'}, default 'last' @@ -3420,9 +3420,9 @@ def argsort(self, axis=0, kind="quicksort", order=None) -> "Series": ---------- axis : {0 or "index"} Has no effect but is accepted for compatibility with numpy. - kind : {'mergesort', 'quicksort', 'heapsort'}, default 'quicksort' - Choice of sorting algorithm. See np.sort for more - information. 'mergesort' is the only stable algorithm. + kind : {'mergesort', 'quicksort', 'heapsort', 'stable'}, default 'quicksort' + Choice of sorting algorithm. See :func:`numpy.sort` for more + information. 'mergesort' and 'stable' are the only stable algorithms. order : None Has no effect but is accepted for compatibility with numpy. diff --git a/pandas/core/sorting.py b/pandas/core/sorting.py index 0a1cbc6de1cda..90396f1be0755 100644 --- a/pandas/core/sorting.py +++ b/pandas/core/sorting.py @@ -54,7 +54,7 @@ def get_indexer_indexer( target : Index level : int or level name or list of ints or list of level names ascending : bool or list of bools, default True - kind : {'quicksort', 'mergesort', 'heapsort'}, default 'quicksort' + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, default 'quicksort' na_position : {'first', 'last'}, default 'last' sort_remaining : bool, default True key : callable, optional diff --git a/pandas/tests/series/methods/test_sort_index.py b/pandas/tests/series/methods/test_sort_index.py index 6c6be1506255a..ccaa8a797e312 100644 --- a/pandas/tests/series/methods/test_sort_index.py +++ b/pandas/tests/series/methods/test_sort_index.py @@ -7,6 +7,11 @@ import pandas._testing as tm +@pytest.fixture(params=["quicksort", "mergesort", "heapsort", "stable"]) +def sort_kind(request): + return request.param + + class TestSeriesSortIndex: def test_sort_index_name(self, datetime_series): result = datetime_series.sort_index(ascending=False) @@ -104,18 +109,12 @@ def test_sort_index_multiindex(self, level): res = s.sort_index(level=level, sort_remaining=False) tm.assert_series_equal(s, res) - def test_sort_index_kind(self): + def test_sort_index_kind(self, sort_kind): # GH#14444 & GH#13589: Add support for sort algo choosing series = Series(index=[3, 2, 1, 4, 3], dtype=object) expected_series = Series(index=[1, 2, 3, 3, 4], dtype=object) - index_sorted_series = series.sort_index(kind="mergesort") - tm.assert_series_equal(expected_series, index_sorted_series) - - index_sorted_series = series.sort_index(kind="quicksort") - tm.assert_series_equal(expected_series, index_sorted_series) - - index_sorted_series = series.sort_index(kind="heapsort") + index_sorted_series = series.sort_index(kind=sort_kind) tm.assert_series_equal(expected_series, index_sorted_series) def test_sort_index_na_position(self): @@ -251,32 +250,20 @@ def test_sort_index_key_int(self): result = series.sort_index(key=lambda x: 2 * x) tm.assert_series_equal(result, series) - def test_sort_index_kind_key(self, sort_by_key): + def test_sort_index_kind_key(self, sort_kind, sort_by_key): # GH #14444 & #13589: Add support for sort algo choosing series = Series(index=[3, 2, 1, 4, 3], dtype=object) expected_series = Series(index=[1, 2, 3, 3, 4], dtype=object) - index_sorted_series = series.sort_index(kind="mergesort", key=sort_by_key) - tm.assert_series_equal(expected_series, index_sorted_series) - - index_sorted_series = series.sort_index(kind="quicksort", key=sort_by_key) - tm.assert_series_equal(expected_series, index_sorted_series) - - index_sorted_series = series.sort_index(kind="heapsort", key=sort_by_key) + index_sorted_series = series.sort_index(kind=sort_kind, key=sort_by_key) tm.assert_series_equal(expected_series, index_sorted_series) - def test_sort_index_kind_neg_key(self): + def test_sort_index_kind_neg_key(self, sort_kind): # GH #14444 & #13589: Add support for sort algo choosing series = Series(index=[3, 2, 1, 4, 3], dtype=object) expected_series = Series(index=[4, 3, 3, 2, 1], dtype=object) - index_sorted_series = series.sort_index(kind="mergesort", key=lambda x: -x) - tm.assert_series_equal(expected_series, index_sorted_series) - - index_sorted_series = series.sort_index(kind="quicksort", key=lambda x: -x) - tm.assert_series_equal(expected_series, index_sorted_series) - - index_sorted_series = series.sort_index(kind="heapsort", key=lambda x: -x) + index_sorted_series = series.sort_index(kind=sort_kind, key=lambda x: -x) tm.assert_series_equal(expected_series, index_sorted_series) def test_sort_index_na_position_key(self, sort_by_key):