diff --git a/pandas/_typing.py b/pandas/_typing.py index 2b42a0a3efb44..8cab908d62507 100644 --- a/pandas/_typing.py +++ b/pandas/_typing.py @@ -307,10 +307,12 @@ def closed(self) -> bool: XMLParsers = Literal["lxml", "etree"] # Interval closed type - IntervalClosedType = Literal["left", "right", "both", "neither"] # datetime and NaTType - DatetimeNaTType = Union[datetime, "NaTType"] DateTimeErrorChoices = Literal["ignore", "raise", "coerce"] + +# sort_index +SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"] +NaPosition = Literal["first", "last"] diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 27048b82e674c..a7c2aa7c551c5 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -61,10 +61,12 @@ IndexKeyFunc, IndexLabel, Level, + NaPosition, PythonFuncType, ReadBuffer, Renamer, Scalar, + SortKind, StorageOptions, Suffixes, TimedeltaConvertibleTypes, @@ -6426,19 +6428,68 @@ def sort_values( # type: ignore[override] else: return result.__finalize__(self, method="sort_values") - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + @overload + def sort_index( + self, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool | Sequence[bool] = ..., + inplace: Literal[True], + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool = ..., + ignore_index: bool = ..., + key: IndexKeyFunc = ..., + ) -> None: + ... + + @overload + def sort_index( + self, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool | Sequence[bool] = ..., + inplace: Literal[False] = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool = ..., + ignore_index: bool = ..., + key: IndexKeyFunc = ..., + ) -> DataFrame: + ... + + @overload def sort_index( + self, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool | Sequence[bool] = ..., + inplace: bool = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool = ..., + ignore_index: bool = ..., + key: IndexKeyFunc = ..., + ) -> DataFrame | None: + ... + + # error: Signature of "sort_index" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def sort_index( # type: ignore[override] self, axis: Axis = 0, level: Level | None = None, - ascending: bool | int | Sequence[bool | int] = True, + ascending: bool | Sequence[bool] = True, inplace: bool = False, - kind: str = "quicksort", - na_position: str = "last", + kind: SortKind = "quicksort", + na_position: NaPosition = "last", sort_remaining: bool = True, ignore_index: bool = False, key: IndexKeyFunc = None, - ): + ) -> DataFrame | None: """ Sort object by labels (along an axis). @@ -6529,15 +6580,15 @@ def sort_index( d 4 """ return super().sort_index( - axis, - level, - ascending, - inplace, - kind, - na_position, - sort_remaining, - ignore_index, - key, + axis=axis, + level=level, + ascending=ascending, + inplace=inplace, + kind=kind, + na_position=na_position, + sort_remaining=sort_remaining, + ignore_index=ignore_index, + key=key, ) def value_counts( diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 649cab26d1b9c..d00a2778848ae 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -50,9 +50,11 @@ JSONSerializable, Level, Manager, + NaPosition, NDFrameT, RandomState, Renamer, + SortKind, StorageOptions, T, TimedeltaConvertibleTypes, @@ -4683,18 +4685,66 @@ def sort_values( """ raise AbstractMethodError(self) + @overload def sort_index( self, - axis=0, - level=None, - ascending: bool_t | int | Sequence[bool_t | int] = True, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool_t | Sequence[bool_t] = ..., + inplace: Literal[True], + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool_t = ..., + ignore_index: bool_t = ..., + key: IndexKeyFunc = ..., + ) -> None: + ... + + @overload + def sort_index( + self: NDFrameT, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool_t | Sequence[bool_t] = ..., + inplace: Literal[False] = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool_t = ..., + ignore_index: bool_t = ..., + key: IndexKeyFunc = ..., + ) -> NDFrameT: + ... + + @overload + def sort_index( + self: NDFrameT, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool_t | Sequence[bool_t] = ..., + inplace: bool_t = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool_t = ..., + ignore_index: bool_t = ..., + key: IndexKeyFunc = ..., + ) -> NDFrameT | None: + ... + + def sort_index( + self: NDFrameT, + axis: Axis = 0, + level: Level | None = None, + ascending: bool_t | Sequence[bool_t] = True, inplace: bool_t = False, - kind: str = "quicksort", - na_position: str = "last", + kind: SortKind = "quicksort", + na_position: NaPosition = "last", sort_remaining: bool_t = True, ignore_index: bool_t = False, key: IndexKeyFunc = None, - ): + ) -> NDFrameT | None: inplace = validate_bool_kwarg(inplace, "inplace") axis = self._get_axis_number(axis) @@ -4715,7 +4765,7 @@ def sort_index( if ignore_index: result.index = default_index(len(self)) if inplace: - return + return None else: return result diff --git a/pandas/core/series.py b/pandas/core/series.py index 44e8283ff08bb..f53c82972a602 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -39,7 +39,10 @@ DtypeObj, FillnaOptions, IndexKeyFunc, + Level, + NaPosition, SingleManager, + SortKind, StorageOptions, TimedeltaConvertibleTypes, TimestampConvertibleTypes, @@ -3575,19 +3578,68 @@ def sort_values( else: return result.__finalize__(self, method="sort_values") - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + @overload def sort_index( self, - axis=0, - level=None, - ascending: bool | int | Sequence[bool | int] = True, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool | Sequence[bool] = ..., + inplace: Literal[True], + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool = ..., + ignore_index: bool = ..., + key: IndexKeyFunc = ..., + ) -> None: + ... + + @overload + def sort_index( + self, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool | Sequence[bool] = ..., + inplace: Literal[False] = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool = ..., + ignore_index: bool = ..., + key: IndexKeyFunc = ..., + ) -> Series: + ... + + @overload + def sort_index( + self, + *, + axis: Axis = ..., + level: Level | None = ..., + ascending: bool | Sequence[bool] = ..., + inplace: bool = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., + sort_remaining: bool = ..., + ignore_index: bool = ..., + key: IndexKeyFunc = ..., + ) -> Series | None: + ... + + # error: Signature of "sort_index" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def sort_index( # type: ignore[override] + self, + axis: Axis = 0, + level: Level | None = None, + ascending: bool | Sequence[bool] = True, inplace: bool = False, - kind: str = "quicksort", - na_position: str = "last", + kind: SortKind = "quicksort", + na_position: NaPosition = "last", sort_remaining: bool = True, ignore_index: bool = False, key: IndexKeyFunc = None, - ): + ) -> Series | None: """ Sort Series by index labels. @@ -3724,15 +3776,15 @@ def sort_index( """ return super().sort_index( - axis, - level, - ascending, - inplace, - kind, - na_position, - sort_remaining, - ignore_index, - key, + axis=axis, + level=level, + ascending=ascending, + inplace=inplace, + kind=kind, + na_position=na_position, + sort_remaining=sort_remaining, + ignore_index=ignore_index, + key=key, ) def argsort(self, axis=0, kind="quicksort", order=None) -> Series: diff --git a/pandas/core/sorting.py b/pandas/core/sorting.py index d41947510c1bb..16facfc915e40 100644 --- a/pandas/core/sorting.py +++ b/pandas/core/sorting.py @@ -9,6 +9,7 @@ Hashable, Iterable, Sequence, + cast, ) import warnings @@ -22,7 +23,10 @@ from pandas._libs.hashtable import unique_label_indices from pandas._typing import ( IndexKeyFunc, + Level, + NaPosition, Shape, + SortKind, npt, ) @@ -47,10 +51,10 @@ def get_indexer_indexer( target: Index, - level: str | int | list[str] | list[int], - ascending: Sequence[bool | int] | bool | int, - kind: str, - na_position: str, + level: Level | list[Level] | None, + ascending: Sequence[bool] | bool, + kind: SortKind, + na_position: NaPosition, sort_remaining: bool, key: IndexKeyFunc, ) -> npt.NDArray[np.intp] | None: @@ -92,8 +96,12 @@ def get_indexer_indexer( ): return None + # ascending can only be a Sequence for MultiIndex indexer = nargsort( - target, kind=kind, ascending=ascending, na_position=na_position + target, + kind=kind, + ascending=cast(bool, ascending), + na_position=na_position, ) return indexer