diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 7e292f4ccf8cb..159c0bb2e72c0 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -948,7 +948,7 @@ def value_counts( # Called once from SparseArray, otherwise could be private def value_counts_arraylike( values: np.ndarray, dropna: bool, mask: npt.NDArray[np.bool_] | None = None -): +) -> tuple[ArrayLike, npt.NDArray[np.int64]]: """ Parameters ---------- diff --git a/pandas/core/arrays/masked.py b/pandas/core/arrays/masked.py index 0a25be38e81df..2fce5fc747312 100644 --- a/pandas/core/arrays/masked.py +++ b/pandas/core/arrays/masked.py @@ -945,9 +945,9 @@ def value_counts(self, dropna: bool = True) -> Series: index = index.astype(self.dtype) mask = np.zeros(len(counts), dtype="bool") - counts = IntegerArray(counts, mask) + counts_array = IntegerArray(counts, mask) - return Series(counts, index=index) + return Series(counts_array, index=index) @doc(ExtensionArray.equals) def equals(self, other) -> bool: diff --git a/pandas/core/arrays/sparse/array.py b/pandas/core/arrays/sparse/array.py index 26c577886f174..e7c745e902a49 100644 --- a/pandas/core/arrays/sparse/array.py +++ b/pandas/core/arrays/sparse/array.py @@ -889,12 +889,20 @@ def value_counts(self, dropna: bool = True) -> Series: if mask.any(): counts[mask] += fcounts else: - keys = np.insert(keys, 0, self.fill_value) + # error: Argument 1 to "insert" has incompatible type "Union[ + # ExtensionArray,ndarray[Any, Any]]"; expected "Union[ + # _SupportsArray[dtype[Any]], Sequence[_SupportsArray[dtype + # [Any]]], Sequence[Sequence[_SupportsArray[dtype[Any]]]], + # Sequence[Sequence[Sequence[_SupportsArray[dtype[Any]]]]], Sequence + # [Sequence[Sequence[Sequence[_SupportsArray[dtype[Any]]]]]]]" + keys = np.insert(keys, 0, self.fill_value) # type: ignore[arg-type] counts = np.insert(counts, 0, fcounts) if not isinstance(keys, ABCIndex): - keys = Index(keys) - return Series(counts, index=keys) + index = Index(keys) + else: + index = keys + return Series(counts, index=index) def _quantile(self, qs: npt.NDArray[np.float64], interpolation: str): diff --git a/pandas/core/base.py b/pandas/core/base.py index 33dbc292660d0..1fa840bcbd51f 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -81,7 +81,10 @@ NumpyValueArrayLike, ) - from pandas import Categorical + from pandas import ( + Categorical, + Series, + ) _shared_docs: dict[str, str] = {} @@ -161,7 +164,7 @@ def _freeze(self): object.__setattr__(self, "__frozen", True) # prevent adding any attribute via s.xxx.new_attribute = ... - def __setattr__(self, key: str, value): + def __setattr__(self, key: str, value) -> None: # _cache is used by a decorator # We need to check both 1.) cls.__dict__ and 2.) getattr(self, key) # because @@ -765,7 +768,7 @@ def hasnans(self) -> bool: # has no attribute "any" return bool(isna(self).any()) # type: ignore[union-attr] - def isna(self): + def isna(self) -> npt.NDArray[np.bool_]: return isna(self._values) def _reduce( @@ -890,7 +893,7 @@ def value_counts( ascending: bool = False, bins=None, dropna: bool = True, - ): + ) -> Series: """ Return a Series containing counts of unique values. diff --git a/pandas/core/common.py b/pandas/core/common.py index 707201153e44a..980e7a79414ba 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -553,7 +553,7 @@ def temp_setattr(obj, attr: str, value) -> Iterator[None]: setattr(obj, attr, old_value) -def require_length_match(data, index: Index): +def require_length_match(data, index: Index) -> None: """ Check the length of data matches the length of the index. """ @@ -665,7 +665,9 @@ def resolve_numeric_only(numeric_only: bool | None | lib.NoDefault) -> bool: return result -def deprecate_numeric_only_default(cls: type, name: str, deprecate_none: bool = False): +def deprecate_numeric_only_default( + cls: type, name: str, deprecate_none: bool = False +) -> None: """Emit FutureWarning message for deprecation of numeric_only. See GH#46560 for details on the deprecation. diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 47cf64ba24022..a49e35539656f 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -37,7 +37,7 @@ """ -def use_bottleneck_cb(key): +def use_bottleneck_cb(key) -> None: from pandas.core import nanops nanops.set_use_bottleneck(cf.get_option(key)) @@ -51,7 +51,7 @@ def use_bottleneck_cb(key): """ -def use_numexpr_cb(key): +def use_numexpr_cb(key) -> None: from pandas.core.computation import expressions expressions.set_use_numexpr(cf.get_option(key)) @@ -65,7 +65,7 @@ def use_numexpr_cb(key): """ -def use_numba_cb(key): +def use_numba_cb(key) -> None: from pandas.core.util import numba_ numba_.set_use_numba(cf.get_option(key)) @@ -329,7 +329,7 @@ def use_numba_cb(key): """ -def table_schema_cb(key): +def table_schema_cb(key) -> None: from pandas.io.formats.printing import enable_data_resource_formatter enable_data_resource_formatter(cf.get_option(key)) @@ -500,7 +500,7 @@ def _deprecate_negative_int_max_colwidth(key): # or we'll hit circular deps. -def use_inf_as_na_cb(key): +def use_inf_as_na_cb(key) -> None: from pandas.core.dtypes.missing import _use_inf_as_na _use_inf_as_na(key) @@ -720,7 +720,7 @@ def use_inf_as_na_cb(key): """ -def register_plotting_backend_cb(key): +def register_plotting_backend_cb(key) -> None: if key == "matplotlib": # We defer matplotlib validation, since it's the default return @@ -746,7 +746,7 @@ def register_plotting_backend_cb(key): """ -def register_converter_cb(key): +def register_converter_cb(key) -> None: from pandas.plotting import ( deregister_matplotlib_converters, register_matplotlib_converters, diff --git a/pandas/core/flags.py b/pandas/core/flags.py index 001cd3d41177a..b4e1039e216c0 100644 --- a/pandas/core/flags.py +++ b/pandas/core/flags.py @@ -81,7 +81,7 @@ def allows_duplicate_labels(self) -> bool: return self._allows_duplicate_labels @allows_duplicate_labels.setter - def allows_duplicate_labels(self, value: bool): + def allows_duplicate_labels(self, value: bool) -> None: value = bool(value) obj = self._obj() if obj is None: @@ -99,12 +99,12 @@ def __getitem__(self, key): return getattr(self, key) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: if key not in self._keys: raise ValueError(f"Unknown flag {key}. Must be one of {self._keys}") setattr(self, key, value) - def __repr__(self): + def __repr__(self) -> str: return f"" def __eq__(self, other): diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c96e306c78347..ead4ea744c647 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1601,7 +1601,7 @@ def __matmul__(self, other: AnyArrayLike | DataFrame) -> DataFrame | Series: """ return self.dot(other) - def __rmatmul__(self, other): + def __rmatmul__(self, other) -> DataFrame: """ Matrix multiplication using binary `@` operator in Python>=3.5. """ @@ -2791,6 +2791,32 @@ def to_markdown( handles.handle.write(result) return None + @overload + def to_parquet( + self, + path: None = ..., + engine: str = ..., + compression: str | None = ..., + index: bool | None = ..., + partition_cols: list[str] | None = ..., + storage_options: StorageOptions = ..., + **kwargs, + ) -> bytes: + ... + + @overload + def to_parquet( + self, + path: FilePath | WriteBuffer[bytes], + engine: str = ..., + compression: str | None = ..., + index: bool | None = ..., + partition_cols: list[str] | None = ..., + storage_options: StorageOptions = ..., + **kwargs, + ) -> None: + ... + @doc(storage_options=_shared_docs["storage_options"]) @deprecate_kwarg(old_arg_name="fname", new_arg_name="path") def to_parquet( @@ -2988,6 +3014,64 @@ def to_orc( self, path, engine=engine, index=index, engine_kwargs=engine_kwargs ) + @overload + def to_html( + self, + buf: FilePath | WriteBuffer[str], + columns: Sequence[Level] | None = ..., + col_space: ColspaceArgType | None = ..., + header: bool | Sequence[str] = ..., + index: bool = ..., + na_rep: str = ..., + formatters: FormattersType | None = ..., + float_format: FloatFormatType | None = ..., + sparsify: bool | None = ..., + index_names: bool = ..., + justify: str | None = ..., + max_rows: int | None = ..., + max_cols: int | None = ..., + show_dimensions: bool | str = ..., + decimal: str = ..., + bold_rows: bool = ..., + classes: str | list | tuple | None = ..., + escape: bool = ..., + notebook: bool = ..., + border: int | bool | None = ..., + table_id: str | None = ..., + render_links: bool = ..., + encoding: str | None = ..., + ) -> None: + ... + + @overload + def to_html( + self, + buf: None = ..., + columns: Sequence[Level] | None = ..., + col_space: ColspaceArgType | None = ..., + header: bool | Sequence[str] = ..., + index: bool = ..., + na_rep: str = ..., + formatters: FormattersType | None = ..., + float_format: FloatFormatType | None = ..., + sparsify: bool | None = ..., + index_names: bool = ..., + justify: str | None = ..., + max_rows: int | None = ..., + max_cols: int | None = ..., + show_dimensions: bool | str = ..., + decimal: str = ..., + bold_rows: bool = ..., + classes: str | list | tuple | None = ..., + escape: bool = ..., + notebook: bool = ..., + border: int | bool | None = ..., + table_id: str | None = ..., + render_links: bool = ..., + encoding: str | None = ..., + ) -> str: + ... + @Substitution( header_type="bool", header="Whether to print column labels, default True", @@ -3001,7 +3085,7 @@ def to_orc( def to_html( self, buf: FilePath | WriteBuffer[str] | None = None, - columns: Sequence[str] | None = None, + columns: Sequence[Level] | None = None, col_space: ColspaceArgType | None = None, header: bool | Sequence[str] = True, index: bool = True, @@ -3023,7 +3107,7 @@ def to_html( table_id: str | None = None, render_links: bool = False, encoding: str | None = None, - ): + ) -> str | None: """ Render a DataFrame as an HTML table. %(shared_params)s @@ -4136,7 +4220,20 @@ def _maybe_cache_changed(self, item, value: Series, inplace: bool) -> None: # ---------------------------------------------------------------------- # Unsorted - def query(self, expr: str, inplace: bool = False, **kwargs): + @overload + def query(self, expr: str, *, inplace: Literal[False] = ..., **kwargs) -> DataFrame: + ... + + @overload + def query(self, expr: str, *, inplace: Literal[True], **kwargs) -> None: + ... + + @overload + def query(self, expr: str, *, inplace: bool = ..., **kwargs) -> DataFrame | None: + ... + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "expr"]) + def query(self, expr: str, inplace: bool = False, **kwargs) -> DataFrame | None: """ Query the columns of a DataFrame with a boolean expression. @@ -4283,7 +4380,7 @@ def query(self, expr: str, inplace: bool = False, **kwargs): if not isinstance(expr, str): msg = f"expr must be a string to be evaluated, {type(expr)} given" raise ValueError(msg) - kwargs["level"] = kwargs.pop("level", 0) + 1 + kwargs["level"] = kwargs.pop("level", 0) + 2 kwargs["target"] = None res = self.eval(expr, **kwargs) @@ -4300,7 +4397,16 @@ def query(self, expr: str, inplace: bool = False, **kwargs): else: return result - def eval(self, expr: str, inplace: bool = False, **kwargs): + @overload + def eval(self, expr: str, *, inplace: Literal[False] = ..., **kwargs) -> Any: + ... + + @overload + def eval(self, expr: str, *, inplace: Literal[True], **kwargs) -> None: + ... + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "expr"]) + def eval(self, expr: str, inplace: bool = False, **kwargs) -> Any | None: """ Evaluate a string describing operations on DataFrame columns. @@ -4406,7 +4512,7 @@ def eval(self, expr: str, inplace: bool = False, **kwargs): from pandas.core.computation.eval import eval as _eval inplace = validate_bool_kwarg(inplace, "inplace") - kwargs["level"] = kwargs.pop("level", 0) + 1 + kwargs["level"] = kwargs.pop("level", 0) + 2 index_resolvers = self._get_index_resolvers() column_resolvers = self._get_cleaned_column_resolvers() resolvers = column_resolvers, index_resolvers @@ -4903,21 +5009,17 @@ def align( @overload def set_axis( - self, labels, axis: Axis = ..., inplace: Literal[False] = ... + self, labels, *, axis: Axis = ..., inplace: Literal[False] = ... ) -> DataFrame: ... @overload - def set_axis(self, labels, axis: Axis, inplace: Literal[True]) -> None: - ... - - @overload - def set_axis(self, labels, *, inplace: Literal[True]) -> None: + def set_axis(self, labels, *, axis: Axis = ..., inplace: Literal[True]) -> None: ... @overload def set_axis( - self, labels, axis: Axis = ..., inplace: bool = ... + self, labels, *, axis: Axis = ..., inplace: bool = ... ) -> DataFrame | None: ... @@ -4988,11 +5090,11 @@ def reindex(self, *args, **kwargs) -> DataFrame: @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: Literal[True], errors: IgnoreRaise = ..., @@ -5002,11 +5104,11 @@ def drop( @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: Literal[False] = ..., errors: IgnoreRaise = ..., @@ -5016,11 +5118,11 @@ def drop( @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: bool = ..., errors: IgnoreRaise = ..., @@ -5032,10 +5134,10 @@ def drop( @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "labels"]) def drop( # type: ignore[override] self, - labels: Hashable | list[Hashable] = None, + labels: IndexLabel = None, axis: Axis = 0, - index: Hashable | list[Hashable] = None, - columns: Hashable | list[Hashable] = None, + index: IndexLabel = None, + columns: IndexLabel = None, level: Level | None = None, inplace: bool = False, errors: IgnoreRaise = "raise", @@ -5540,16 +5642,47 @@ def pop(self, item: Hashable) -> Series: """ return super().pop(item=item) - @doc(NDFrame.replace, **_shared_doc_kwargs) + # error: Signature of "replace" incompatible with supertype "NDFrame" + @overload # type: ignore[override] def replace( + self, + to_replace=..., + value=..., + *, + inplace: Literal[False] = ..., + limit: int | None = ..., + regex: bool = ..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> DataFrame: + ... + + @overload + def replace( + self, + to_replace=..., + value=..., + *, + inplace: Literal[True], + limit: int | None = ..., + regex: bool = ..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> None: + ... + + # error: Signature of "replace" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "to_replace", "value"] + ) + @doc(NDFrame.replace, **_shared_doc_kwargs) + def replace( # type: ignore[override] self, to_replace=None, value=lib.no_default, inplace: bool = False, - limit=None, + limit: int | None = None, regex: bool = False, method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = lib.no_default, - ): + ) -> DataFrame | None: return super().replace( to_replace=to_replace, value=value, @@ -5681,6 +5814,30 @@ def shift( periods=periods, freq=freq, axis=axis, fill_value=fill_value ) + @overload + def set_index( + self, + keys, + *, + drop: bool = ..., + append: bool = ..., + inplace: Literal[False] = ..., + verify_integrity: bool = ..., + ) -> DataFrame: + ... + + @overload + def set_index( + self, + keys, + *, + drop: bool = ..., + append: bool = ..., + inplace: Literal[True], + verify_integrity: bool = ..., + ) -> None: + ... + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "keys"]) def set_index( self, @@ -5689,7 +5846,7 @@ def set_index( append: bool = False, inplace: bool = False, verify_integrity: bool = False, - ): + ) -> DataFrame | None: """ Set the DataFrame index using existing columns. @@ -5882,6 +6039,7 @@ def set_index( if not inplace: return frame + return None @overload def reset_index( @@ -6232,6 +6390,30 @@ def notnull(self) -> DataFrame: """ return ~self.isna() + @overload + def dropna( + self, + *, + axis: Axis = ..., + how: str | NoDefault = ..., + thresh: int | NoDefault = ..., + subset: IndexLabel = ..., + inplace: Literal[False] = ..., + ) -> DataFrame: + ... + + @overload + def dropna( + self, + *, + axis: Axis = ..., + how: str | NoDefault = ..., + thresh: int | NoDefault = ..., + subset: IndexLabel = ..., + inplace: Literal[True], + ) -> None: + ... + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) def dropna( self, @@ -6240,7 +6422,7 @@ def dropna( thresh: int | NoDefault = no_default, subset: IndexLabel = None, inplace: bool = False, - ): + ) -> DataFrame | None: """ Remove missing values. @@ -6389,10 +6571,10 @@ def dropna( else: result = self.loc(axis=axis)[mask] - if inplace: - self._update_inplace(result) - else: + if not inplace: return result + self._update_inplace(result) + return None @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "subset"]) def drop_duplicates( @@ -6637,11 +6819,42 @@ def f(vals) -> tuple[np.ndarray, int]: # ---------------------------------------------------------------------- # Sorting + # error: Signature of "sort_values" incompatible with supertype "NDFrame" + @overload # type: ignore[override] + def sort_values( + self, + by, + *, + axis: Axis = ..., + ascending=..., + inplace: Literal[False] = ..., + kind: str = ..., + na_position: str = ..., + ignore_index: bool = ..., + key: ValueKeyFunc = ..., + ) -> DataFrame: + ... + + @overload + def sort_values( + self, + by, + *, + axis: Axis = ..., + ascending=..., + inplace: Literal[True], + kind: str = ..., + na_position: str = ..., + ignore_index: bool = ..., + key: ValueKeyFunc = ..., + ) -> None: + ... + # TODO: Just move the sort_values doc here. + # error: Signature of "sort_values" incompatible with supertype "NDFrame" @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "by"]) @Substitution(**_shared_doc_kwargs) @Appender(NDFrame.sort_values.__doc__) - # error: Signature of "sort_values" incompatible with supertype "NDFrame" def sort_values( # type: ignore[override] self, by, @@ -6652,7 +6865,7 @@ def sort_values( # type: ignore[override] na_position: str = "last", ignore_index: bool = False, key: ValueKeyFunc = None, - ): + ) -> DataFrame | None: inplace = validate_bool_kwarg(inplace, "inplace") axis = self._get_axis_number(axis) ascending = validate_ascending(ascending) @@ -6884,7 +7097,7 @@ def value_counts( sort: bool = True, ascending: bool = False, dropna: bool = True, - ): + ) -> Series: """ Return a Series containing counts of unique rows in the DataFrame. @@ -11407,25 +11620,93 @@ def values(self) -> np.ndarray: self._consolidate_inplace() return self._mgr.as_array() - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + @overload def ffill( - self: DataFrame, + self, + *, + axis: None | Axis = ..., + inplace: Literal[False] = ..., + limit: None | int = ..., + downcast=..., + ) -> DataFrame: + ... + + @overload + def ffill( + self, + *, + axis: None | Axis = ..., + inplace: Literal[True], + limit: None | int = ..., + downcast=..., + ) -> None: + ... + + @overload + def ffill( + self, + *, + axis: None | Axis = ..., + inplace: bool = ..., + limit: None | int = ..., + downcast=..., + ) -> DataFrame | None: + ... + + # error: Signature of "ffill" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def ffill( # type: ignore[override] + self, axis: None | Axis = None, inplace: bool = False, limit: None | int = None, downcast=None, ) -> DataFrame | None: - return super().ffill(axis, inplace, limit, downcast) + return super().ffill(axis=axis, inplace=inplace, limit=limit, downcast=downcast) - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + @overload def bfill( - self: DataFrame, + self, + *, + axis: None | Axis = ..., + inplace: Literal[False] = ..., + limit: None | int = ..., + downcast=..., + ) -> DataFrame: + ... + + @overload + def bfill( + self, + *, + axis: None | Axis = ..., + inplace: Literal[True], + limit: None | int = ..., + downcast=..., + ) -> None: + ... + + @overload + def bfill( + self, + *, + axis: None | Axis = ..., + inplace: bool = ..., + limit: None | int = ..., + downcast=..., + ) -> DataFrame | None: + ... + + # error: Signature of "bfill" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def bfill( # type: ignore[override] + self, axis: None | Axis = None, inplace: bool = False, limit: None | int = None, downcast=None, ) -> DataFrame | None: - return super().bfill(axis, inplace, limit, downcast) + return super().bfill(axis=axis, inplace=inplace, limit=limit, downcast=downcast) @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "lower", "upper"] @@ -11464,35 +11745,137 @@ def interpolate( **kwargs, ) + @overload + def where( + self, + cond, + other=..., + *, + inplace: Literal[False] = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> DataFrame: + ... + + @overload + def where( + self, + cond, + other=..., + *, + inplace: Literal[True], + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> None: + ... + + @overload + def where( + self, + cond, + other=..., + *, + inplace: bool = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> DataFrame | None: + ... + + # error: Signature of "where" incompatible with supertype "NDFrame" @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "cond", "other"] ) - def where( + def where( # type: ignore[override] self, cond, other=lib.no_default, - inplace=False, + inplace: bool = False, axis=None, level=None, - errors: IgnoreRaise = "raise", + errors: IgnoreRaise | lib.NoDefault = "raise", try_cast=lib.no_default, - ): - return super().where(cond, other, inplace, axis, level, errors, try_cast) + ) -> DataFrame | None: + return super().where( + cond, + other, + inplace=inplace, + axis=axis, + level=level, + errors=errors, + try_cast=try_cast, + ) + @overload + def mask( + self, + cond, + other=..., + *, + inplace: Literal[False] = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> DataFrame: + ... + + @overload + def mask( + self, + cond, + other=..., + *, + inplace: Literal[True], + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> None: + ... + + @overload + def mask( + self, + cond, + other=..., + *, + inplace: bool = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> DataFrame | None: + ... + + # error: Signature of "mask" incompatible with supertype "NDFrame" @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "cond", "other"] ) - def mask( + def mask( # type: ignore[override] self, cond, other=np.nan, - inplace=False, + inplace: bool = False, axis=None, level=None, - errors: IgnoreRaise = "raise", + errors: IgnoreRaise | lib.NoDefault = "raise", try_cast=lib.no_default, - ): - return super().mask(cond, other, inplace, axis, level, errors, try_cast) + ) -> DataFrame | None: + return super().mask( + cond, + other, + inplace=inplace, + axis=axis, + level=level, + errors=errors, + try_cast=try_cast, + ) DataFrame._add_numeric_operations() diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 76a473dad79a4..ba3474a2513fb 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -699,25 +699,24 @@ def size(self) -> int: @overload def set_axis( - self: NDFrameT, labels, axis: Axis = ..., inplace: Literal[False] = ... + self: NDFrameT, labels, *, axis: Axis = ..., inplace: Literal[False] = ... ) -> NDFrameT: ... @overload - def set_axis(self, labels, axis: Axis, inplace: Literal[True]) -> None: - ... - - @overload - def set_axis(self, labels, *, inplace: Literal[True]) -> None: + def set_axis(self, labels, *, axis: Axis = ..., inplace: Literal[True]) -> None: ... @overload def set_axis( - self: NDFrameT, labels, axis: Axis = ..., inplace: bool_t = ... + self: NDFrameT, labels, *, axis: Axis = ..., inplace: bool_t = ... ) -> NDFrameT | None: ... - def set_axis(self, labels, axis: Axis = 0, inplace: bool_t = False): + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "labels"]) + def set_axis( + self: NDFrameT, labels, axis: Axis = 0, inplace: bool_t = False + ) -> NDFrameT | None: """ Assign desired index to given axis. @@ -1049,10 +1048,44 @@ def _rename( else: return result.__finalize__(self, method="rename") - @rewrite_axis_style_signature("mapper", [("copy", True), ("inplace", False)]) + @overload def rename_axis( - self, mapper: IndexLabel | lib.NoDefault = lib.no_default, **kwargs - ): + self: NDFrameT, + mapper: IndexLabel | lib.NoDefault = ..., + *, + inplace: Literal[False] = ..., + **kwargs, + ) -> NDFrameT: + ... + + @overload + def rename_axis( + self, + mapper: IndexLabel | lib.NoDefault = ..., + *, + inplace: Literal[True], + **kwargs, + ) -> None: + ... + + @overload + def rename_axis( + self: NDFrameT, + mapper: IndexLabel | lib.NoDefault = ..., + *, + inplace: bool_t = ..., + **kwargs, + ) -> NDFrameT | None: + ... + + @rewrite_axis_style_signature("mapper", [("copy", True)]) + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "mapper"]) + def rename_axis( + self: NDFrameT, + mapper: IndexLabel | lib.NoDefault = lib.no_default, + inplace: bool_t = False, + **kwargs, + ) -> NDFrameT | None: """ Set the name of the axis for the index or columns. @@ -1176,6 +1209,7 @@ class name cat 4 0 monkey 2 2 """ + kwargs["inplace"] = inplace axes, kwargs = self._construct_axes_from_arguments( (), kwargs, sentinel=lib.no_default ) @@ -1221,6 +1255,7 @@ class name result._set_axis_name(newnames, axis=axis, inplace=True) if not inplace: return result + return None @final def _set_axis_name(self, name, axis=0, inplace=False): @@ -1379,7 +1414,7 @@ def equals(self, other: object) -> bool_t: # Unary Methods @final - def __neg__(self): + def __neg__(self: NDFrameT) -> NDFrameT: def blk_func(values: ArrayLike): if is_bool_dtype(values.dtype): # error: Argument 1 to "inv" has incompatible type "Union @@ -1397,7 +1432,7 @@ def blk_func(values: ArrayLike): return res.__finalize__(self, method="__neg__") @final - def __pos__(self): + def __pos__(self: NDFrameT) -> NDFrameT: def blk_func(values: ArrayLike): if is_bool_dtype(values.dtype): return values.copy() @@ -1412,7 +1447,7 @@ def blk_func(values: ArrayLike): return res.__finalize__(self, method="__pos__") @final - def __invert__(self): + def __invert__(self: NDFrameT) -> NDFrameT: if not self.size: # inv fails with 0 len return self @@ -1430,7 +1465,7 @@ def __nonzero__(self): __bool__ = __nonzero__ @final - def bool(self): + def bool(self) -> bool_t: """ Return the bool of a single element Series or DataFrame. @@ -1473,6 +1508,8 @@ def bool(self): ) self.__nonzero__() + # for mypy (__nonzero__ raises) + return True @final def abs(self: NDFrameT) -> NDFrameT: @@ -1733,7 +1770,14 @@ def _get_label_or_level_values(self, key: str, axis: int = 0) -> np.ndarray: self._check_label_or_level_ambiguity(key, axis=axis) values = self.xs(key, axis=other_axes[0])._values elif self._is_level_reference(key, axis=axis): - values = self.axes[axis].get_level_values(key)._values + # error: Incompatible types in assignment (expression has type "Union[ + # ExtensionArray, ndarray[Any, Any]]", variable has type "ndarray[Any, + # Any]") + values = ( + self.axes[axis] + .get_level_values(key) # type: ignore[assignment] + ._values + ) else: raise KeyError(key) @@ -1852,7 +1896,7 @@ def __iter__(self): return iter(self._info_axis) # can we get a better explanation of this? - def keys(self): + def keys(self) -> Index: """ Get the 'info axis' (see Indexing for more). @@ -3293,6 +3337,60 @@ def to_latex( position=position, ) + @overload + def to_csv( + self, + path_or_buf: None = ..., + sep: str = ..., + na_rep: str = ..., + float_format: str | Callable | None = ..., + columns: Sequence[Hashable] | None = ..., + header: bool_t | list[str] = ..., + index: bool_t = ..., + index_label: IndexLabel | None = ..., + mode: str = ..., + encoding: str | None = ..., + compression: CompressionOptions = ..., + quoting: int | None = ..., + quotechar: str = ..., + lineterminator: str | None = ..., + chunksize: int | None = ..., + date_format: str | None = ..., + doublequote: bool_t = ..., + escapechar: str | None = ..., + decimal: str = ..., + errors: str = ..., + storage_options: StorageOptions = ..., + ) -> str: + ... + + @overload + def to_csv( + self, + path_or_buf: FilePath | WriteBuffer[bytes] | WriteBuffer[str], + sep: str = ..., + na_rep: str = ..., + float_format: str | Callable | None = ..., + columns: Sequence[Hashable] | None = ..., + header: bool_t | list[str] = ..., + index: bool_t = ..., + index_label: IndexLabel | None = ..., + mode: str = ..., + encoding: str | None = ..., + compression: CompressionOptions = ..., + quoting: int | None = ..., + quotechar: str = ..., + lineterminator: str | None = ..., + chunksize: int | None = ..., + date_format: str | None = ..., + doublequote: bool_t = ..., + escapechar: str | None = ..., + decimal: str = ..., + errors: str = ..., + storage_options: StorageOptions = ..., + ) -> None: + ... + @final @doc( storage_options=_shared_docs["storage_options"], @@ -3666,7 +3764,9 @@ def _take_with_is_copy(self: NDFrameT, indices, axis=0) -> NDFrameT: return result @final - def xs(self, key, axis=0, level=None, drop_level: bool_t = True): + def xs( + self: NDFrameT, key, axis=0, level=None, drop_level: bool_t = True + ) -> NDFrameT: """ Return cross-section from the Series/DataFrame. @@ -4181,11 +4281,11 @@ def reindex_like( @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: Literal[True], errors: IgnoreRaise = ..., @@ -4195,11 +4295,11 @@ def drop( @overload def drop( self: NDFrameT, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: Literal[False] = ..., errors: IgnoreRaise = ..., @@ -4209,11 +4309,11 @@ def drop( @overload def drop( self: NDFrameT, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: bool_t = ..., errors: IgnoreRaise = ..., @@ -4223,10 +4323,10 @@ def drop( @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "labels"]) def drop( self: NDFrameT, - labels: Hashable | list[Hashable] = None, + labels: IndexLabel = None, axis: Axis = 0, - index: Hashable | list[Hashable] = None, - columns: Hashable | list[Hashable] = None, + index: IndexLabel = None, + columns: IndexLabel = None, level: Level | None = None, inplace: bool_t = False, errors: IgnoreRaise = "raise", @@ -4489,16 +4589,59 @@ def add_suffix(self: NDFrameT, suffix: str) -> NDFrameT: # "**Dict[str, partial[str]]"; expected "Union[str, int, None]" return self._rename(**mapper) # type: ignore[return-value, arg-type] + @overload + def sort_values( + self: NDFrameT, + *, + axis: Axis = ..., + ascending=..., + inplace: Literal[False] = ..., + kind: str = ..., + na_position: str = ..., + ignore_index: bool_t = ..., + key: ValueKeyFunc = ..., + ) -> NDFrameT: + ... + + @overload def sort_values( self, - axis=0, + *, + axis: Axis = ..., + ascending=..., + inplace: Literal[True], + kind: str = ..., + na_position: str = ..., + ignore_index: bool_t = ..., + key: ValueKeyFunc = ..., + ) -> None: + ... + + @overload + def sort_values( + self: NDFrameT, + *, + axis: Axis = ..., + ascending=..., + inplace: bool_t = ..., + kind: str = ..., + na_position: str = ..., + ignore_index: bool_t = ..., + key: ValueKeyFunc = ..., + ) -> NDFrameT | None: + ... + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def sort_values( + self: NDFrameT, + axis: Axis = 0, ascending=True, inplace: bool_t = False, kind: str = "quicksort", na_position: str = "last", ignore_index: bool_t = False, key: ValueKeyFunc = None, - ): + ) -> NDFrameT | None: """ Sort by the values along either axis. @@ -5741,7 +5884,7 @@ def _get_bool_data(self): # Internal Interface Methods @property - def values(self) -> np.ndarray: + def values(self): raise AbstractMethodError(self) @property @@ -6553,6 +6696,40 @@ def fillna( else: return result.__finalize__(self, method="fillna") + @overload + def ffill( + self: NDFrameT, + *, + axis: None | Axis = ..., + inplace: Literal[False] = ..., + limit: None | int = ..., + downcast=..., + ) -> NDFrameT: + ... + + @overload + def ffill( + self, + *, + axis: None | Axis = ..., + inplace: Literal[True], + limit: None | int = ..., + downcast=..., + ) -> None: + ... + + @overload + def ffill( + self: NDFrameT, + *, + axis: None | Axis = ..., + inplace: bool_t = ..., + limit: None | int = ..., + downcast=..., + ) -> NDFrameT | None: + ... + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) @doc(klass=_shared_doc_kwargs["klass"]) def ffill( self: NDFrameT, @@ -6575,6 +6752,40 @@ def ffill( pad = ffill + @overload + def bfill( + self: NDFrameT, + *, + axis: None | Axis = ..., + inplace: Literal[False] = ..., + limit: None | int = ..., + downcast=..., + ) -> NDFrameT: + ... + + @overload + def bfill( + self, + *, + axis: None | Axis = ..., + inplace: Literal[True], + limit: None | int = ..., + downcast=..., + ) -> None: + ... + + @overload + def bfill( + self: NDFrameT, + *, + axis: None | Axis = ..., + inplace: bool_t = ..., + limit: None | int = ..., + downcast=..., + ) -> NDFrameT | None: + ... + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) @doc(klass=_shared_doc_kwargs["klass"]) def bfill( self: NDFrameT, @@ -6597,6 +6808,48 @@ def bfill( backfill = bfill + @overload + def replace( + self: NDFrameT, + to_replace=..., + value=..., + *, + inplace: Literal[False] = ..., + limit: int | None = ..., + regex=..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> NDFrameT: + ... + + @overload + def replace( + self, + to_replace=..., + value=..., + *, + inplace: Literal[True], + limit: int | None = ..., + regex=..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> None: + ... + + @overload + def replace( + self: NDFrameT, + to_replace=..., + value=..., + *, + inplace: bool_t = ..., + limit: int | None = ..., + regex=..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> NDFrameT | None: + ... + + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "to_replace", "value"] + ) @doc( _shared_docs["replace"], klass=_shared_doc_kwargs["klass"], @@ -6604,14 +6857,14 @@ def bfill( replace_iloc=_shared_doc_kwargs["replace_iloc"], ) def replace( - self, + self: NDFrameT, to_replace=None, value=lib.no_default, inplace: bool_t = False, limit: int | None = None, regex=False, method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = lib.no_default, - ): + ) -> NDFrameT | None: if not ( is_scalar(to_replace) or is_re_compilable(to_replace) @@ -6652,9 +6905,8 @@ def replace( args=(to_replace, method, inplace, limit), ) if inplace: - return + return None return result - self = cast("Series", self) return self._replace_single(to_replace, method, inplace, limit) if not is_dict_like(to_replace): @@ -6703,7 +6955,7 @@ def replace( # need a non-zero len on all axes if not self.size: if inplace: - return + return None return self.copy() if is_dict_like(to_replace): @@ -9124,7 +9376,7 @@ def _where( inplace=False, axis=None, level=None, - errors: IgnoreRaise = "raise", + errors: IgnoreRaise | lib.NoDefault = "raise", ): """ Equivalent to public method `where`, except that `other` is not @@ -9249,6 +9501,51 @@ def _where( result = self._constructor(new_data) return result.__finalize__(self) + @overload + def where( + self: NDFrameT, + cond, + other=..., + *, + inplace: Literal[False] = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> NDFrameT: + ... + + @overload + def where( + self, + cond, + other=..., + *, + inplace: Literal[True], + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> None: + ... + + @overload + def where( + self: NDFrameT, + cond, + other=..., + *, + inplace: bool_t = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> NDFrameT | None: + ... + + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "cond", "other"] + ) @doc( klass=_shared_doc_kwargs["klass"], cond="True", @@ -9257,15 +9554,15 @@ def _where( name_other="mask", ) def where( - self, + self: NDFrameT, cond, other=np.nan, - inplace=False, + inplace: bool_t = False, axis=None, level=None, - errors: IgnoreRaise = "raise", + errors: IgnoreRaise | lib.NoDefault = "raise", try_cast=lib.no_default, - ): + ) -> NDFrameT | None: """ Replace values where the condition is {cond_rev}. @@ -9402,6 +9699,51 @@ def where( return self._where(cond, other, inplace, axis, level, errors=errors) + @overload + def mask( + self: NDFrameT, + cond, + other=..., + *, + inplace: Literal[False] = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> NDFrameT: + ... + + @overload + def mask( + self, + cond, + other=..., + *, + inplace: Literal[True], + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> None: + ... + + @overload + def mask( + self: NDFrameT, + cond, + other=..., + *, + inplace: bool_t = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> NDFrameT | None: + ... + + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "cond", "other"] + ) @doc( where, klass=_shared_doc_kwargs["klass"], @@ -9411,15 +9753,15 @@ def where( name_other="where", ) def mask( - self, + self: NDFrameT, cond, other=np.nan, - inplace=False, + inplace: bool_t = False, axis=None, level=None, - errors: IgnoreRaise = "raise", + errors: IgnoreRaise | lib.NoDefault = "raise", try_cast=lib.no_default, - ): + ) -> NDFrameT | None: inplace = validate_bool_kwarg(inplace, "inplace") cond = com.apply_if_callable(cond, self) @@ -11365,7 +11707,7 @@ def rolling( closed: str | None = None, step: int | None = None, method: str = "single", - ): + ) -> Window | Rolling: axis = self._get_axis_number(axis) if win_type is not None: @@ -11477,47 +11819,47 @@ def _inplace_method(self, other, op): ) return self - def __iadd__(self, other): + def __iadd__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for + ("Type[NDFrame]") return self._inplace_method(other, type(self).__add__) # type: ignore[operator] - def __isub__(self, other): + def __isub__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for - ("Type[NDFrame]") return self._inplace_method(other, type(self).__sub__) # type: ignore[operator] - def __imul__(self, other): + def __imul__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for * ("Type[NDFrame]") return self._inplace_method(other, type(self).__mul__) # type: ignore[operator] - def __itruediv__(self, other): + def __itruediv__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for / ("Type[NDFrame]") return self._inplace_method( other, type(self).__truediv__ # type: ignore[operator] ) - def __ifloordiv__(self, other): + def __ifloordiv__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for // ("Type[NDFrame]") return self._inplace_method( other, type(self).__floordiv__ # type: ignore[operator] ) - def __imod__(self, other): + def __imod__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for % ("Type[NDFrame]") return self._inplace_method(other, type(self).__mod__) # type: ignore[operator] - def __ipow__(self, other): + def __ipow__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for ** ("Type[NDFrame]") return self._inplace_method(other, type(self).__pow__) # type: ignore[operator] - def __iand__(self, other): + def __iand__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for & ("Type[NDFrame]") return self._inplace_method(other, type(self).__and__) # type: ignore[operator] - def __ior__(self, other): + def __ior__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for | ("Type[NDFrame]") return self._inplace_method(other, type(self).__or__) # type: ignore[operator] - def __ixor__(self, other): + def __ixor__(self: NDFrameT, other) -> NDFrameT: # error: Unsupported left operand type for ^ ("Type[NDFrame]") return self._inplace_method(other, type(self).__xor__) # type: ignore[operator] diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index b70904db8ae25..665333d0d7b4f 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -5,6 +5,7 @@ TYPE_CHECKING, Hashable, Sequence, + TypeVar, cast, final, ) @@ -74,6 +75,8 @@ Series, ) +_LocationIndexerT = TypeVar("_LocationIndexerT", bound="_LocationIndexer") + # "null slice" _NS = slice(None, None) _one_ellipsis_message = "indexer may only contain one '...' entry" @@ -654,7 +657,7 @@ class _LocationIndexer(NDFrameIndexerBase): _takeable: bool @final - def __call__(self, axis=None): + def __call__(self: _LocationIndexerT, axis=None) -> _LocationIndexerT: # we need to return a copy of ourselves new_self = type(self)(self.name, self.obj) @@ -798,7 +801,7 @@ def _ensure_listlike_indexer(self, key, axis=None, value=None): self.obj._mgr = self.obj._mgr.reindex_axis(keys, axis=0, only_slice=True) @final - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: check_deprecated_indexers(key) if isinstance(key, tuple): key = tuple(list(x) if is_iterator(x) else x for x in key) @@ -2362,7 +2365,7 @@ def __getitem__(self, key): key = self._convert_key(key) return self.obj._get_value(*key, takeable=self._takeable) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: if isinstance(key, tuple): key = tuple(com.apply_if_callable(x, self.obj) for x in key) else: diff --git a/pandas/core/missing.py b/pandas/core/missing.py index 57b0a95f803b1..6005e11efbac4 100644 --- a/pandas/core/missing.py +++ b/pandas/core/missing.py @@ -104,7 +104,7 @@ def mask_missing(arr: ArrayLike, values_to_mask) -> npt.NDArray[np.bool_]: return mask -def clean_fill_method(method, allow_nearest: bool = False): +def clean_fill_method(method: str | None, allow_nearest: bool = False): # asfreq is compat for resampling if method in [None, "asfreq"]: return None @@ -907,7 +907,7 @@ def get_fill_func(method, ndim: int = 1): return {"pad": _pad_2d, "backfill": _backfill_2d}[method] -def clean_reindex_fill_method(method): +def clean_reindex_fill_method(method) -> str | None: return clean_fill_method(method, allow_nearest=True) diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index a96fb9c8129dd..05a9bde700e32 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -5,6 +5,7 @@ import operator from typing import ( Any, + Callable, cast, ) import warnings @@ -1527,7 +1528,7 @@ def _zero_out_fperr(arg): @disallow("M8", "m8") def nancorr( a: np.ndarray, b: np.ndarray, *, method="pearson", min_periods: int | None = None -): +) -> float: """ a, b: ndarrays """ @@ -1549,7 +1550,7 @@ def nancorr( return f(a, b) -def get_corr_func(method): +def get_corr_func(method) -> Callable[[np.ndarray, np.ndarray], float]: if method == "kendall": from scipy.stats import kendalltau @@ -1586,7 +1587,7 @@ def nancov( *, min_periods: int | None = None, ddof: int | None = 1, -): +) -> float: if len(a) != len(b): raise AssertionError("Operands to nancov must have same size") diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 0a62861cdaba7..7306d13e44982 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -1491,7 +1491,9 @@ def _constructor(self): return TimedeltaIndexResampler -def get_resampler(obj, kind=None, **kwds): +def get_resampler( + obj, kind=None, **kwds +) -> DatetimeIndexResampler | PeriodIndexResampler | TimedeltaIndexResampler: """ Create a TimeGrouper and return our resampler. """ diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 8c861c199169b..03aad0ef64dec 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -481,6 +481,7 @@ def pivot( columns_listlike = com.convert_to_list_like(columns) + indexed: DataFrame | Series if values is None: if index is not None: cols = com.convert_to_list_like(index) @@ -517,7 +518,10 @@ def pivot( ) else: indexed = data._constructor_sliced(data[values]._values, index=multiindex) - return indexed.unstack(columns_listlike) + # error: Argument 1 to "unstack" of "DataFrame" has incompatible type "Union + # [List[Any], ExtensionArray, ndarray[Any, Any], Index, Series]"; expected + # "Hashable" + return indexed.unstack(columns_listlike) # type: ignore[arg-type] def crosstab( diff --git a/pandas/core/series.py b/pandas/core/series.py index dd52ec855240e..ef4ea0172c505 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -38,9 +38,11 @@ Axis, Dtype, DtypeObj, + FilePath, FillnaOptions, IgnoreRaise, IndexKeyFunc, + IndexLabel, Level, NaPosition, QuantileInterpolation, @@ -51,6 +53,7 @@ TimedeltaConvertibleTypes, TimestampConvertibleTypes, ValueKeyFunc, + WriteBuffer, npt, ) from pandas.compat.numpy import function as nv @@ -1369,15 +1372,39 @@ def repeat(self, repeats, axis=None) -> Series: self, method="repeat" ) + @overload + def reset_index( + self, + level: Level = ..., + *, + drop: bool = ..., + name: Level = ..., + inplace: Literal[False] = ..., + allow_duplicates: bool = ..., + ) -> Series: + ... + + @overload + def reset_index( + self, + level: Level = ..., + *, + drop: bool = ..., + name: Level = ..., + inplace: Literal[True], + allow_duplicates: bool = ..., + ) -> None: + ... + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "level"]) def reset_index( self, - level=None, - drop=False, - name=lib.no_default, - inplace=False, + level: Level = None, + drop: bool = False, + name: Level = lib.no_default, + inplace: bool = False, allow_duplicates: bool = False, - ): + ) -> Series | None: """ Generate a new DataFrame or Series with the index reset. @@ -1493,11 +1520,14 @@ def reset_index( if drop: new_index = default_index(len(self)) if level is not None: + level_list: Sequence[Hashable] if not isinstance(level, (tuple, list)): - level = [level] - level = [self.index._get_level_number(lev) for lev in level] - if len(level) < self.index.nlevels: - new_index = self.index.droplevel(level) + level_list = [level] + else: + level_list = level + level_list = [self.index._get_level_number(lev) for lev in level_list] + if len(level_list) < self.index.nlevels: + new_index = self.index.droplevel(level_list) if inplace: self.index = new_index @@ -1519,9 +1549,12 @@ def reset_index( name = self.name df = self.to_frame(name) - return df.reset_index( + # error: Incompatible return value type (got "DataFrame", expected + # "Optional[Series]") + return df.reset_index( # type: ignore[return-value] level=level, drop=drop, allow_duplicates=allow_duplicates ) + return None # ---------------------------------------------------------------------- # Rendering Methods @@ -1533,19 +1566,51 @@ def __repr__(self) -> str: repr_params = fmt.get_series_repr_params() return self.to_string(**repr_params) + @overload + def to_string( + self, + buf: None = ..., + na_rep: str = ..., + float_format: str | None = ..., + header: bool = ..., + index: bool = ..., + length=..., + dtype=..., + name=..., + max_rows: int | None = ..., + min_rows: int | None = ..., + ) -> str: + ... + + @overload def to_string( self, - buf=None, - na_rep="NaN", - float_format=None, - header=True, - index=True, + buf: FilePath | WriteBuffer[str], + na_rep: str = ..., + float_format: str | None = ..., + header: bool = ..., + index: bool = ..., + length=..., + dtype=..., + name=..., + max_rows: int | None = ..., + min_rows: int | None = ..., + ) -> None: + ... + + def to_string( + self, + buf: FilePath | WriteBuffer[str] | None = None, + na_rep: str = "NaN", + float_format: str | None = None, + header: bool = True, + index: bool = True, length=False, dtype=False, name=False, - max_rows=None, - min_rows=None, - ): + max_rows: int | None = None, + min_rows: int | None = None, + ) -> str | None: """ Render a string representation of the Series. @@ -1604,11 +1669,17 @@ def to_string( if buf is None: return result else: - try: - buf.write(result) - except AttributeError: - with open(buf, "w") as f: + if hasattr(buf, "write"): + # error: Item "str" of "Union[str, PathLike[str], WriteBuffer + # [str]]" has no attribute "write" + buf.write(result) # type: ignore[union-attr] + else: + # error: Argument 1 to "open" has incompatible type "Union[str, + # PathLike[str], WriteBuffer[str]]"; expected "Union[Union[str, + # bytes, PathLike[str], PathLike[bytes]], int]" + with open(buf, "w") as f: # type: ignore[arg-type] f.write(result) + return None @doc( klass=_shared_doc_kwargs["klass"], @@ -2922,7 +2993,7 @@ def searchsorted( # type: ignore[override] def append( self, to_append, ignore_index: bool = False, verify_integrity: bool = False - ): + ) -> Series: """ Concatenate two or more Series. @@ -3400,17 +3471,47 @@ def update(self, other) -> None: # ---------------------------------------------------------------------- # Reindexing, sorting - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + # error: Signature of "sort_values" incompatible with supertype "NDFrame" + @overload # type: ignore[override] def sort_values( self, - axis=0, - ascending: bool | int | Sequence[bool | int] = True, + *, + axis: Axis = ..., + ascending: bool | int | Sequence[bool] | Sequence[int] = ..., + inplace: Literal[False] = ..., + kind: str = ..., + na_position: str = ..., + ignore_index: bool = ..., + key: ValueKeyFunc = ..., + ) -> Series: + ... + + @overload + def sort_values( + self, + *, + axis: Axis = ..., + ascending: bool | int | Sequence[bool] | Sequence[int] = ..., + inplace: Literal[True], + kind: str = ..., + na_position: str = ..., + ignore_index: bool = ..., + key: ValueKeyFunc = ..., + ) -> None: + ... + + # error: Signature of "sort_values" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def sort_values( # type: ignore[override] + self, + axis: Axis = 0, + ascending: bool | int | Sequence[bool] | Sequence[int] = True, inplace: bool = False, kind: str = "quicksort", na_position: str = "last", ignore_index: bool = False, key: ValueKeyFunc = None, - ): + ) -> Series | None: """ Sort by the values. @@ -3604,10 +3705,10 @@ def sort_values( if ignore_index: result.index = default_index(len(sorted_index)) - if inplace: - self._update_inplace(result) - else: + if not inplace: return result.__finalize__(self, method="sort_values") + self._update_inplace(result) + return None @overload def sort_index( @@ -4819,22 +4920,21 @@ def rename( @overload def set_axis( - self, labels, axis: Axis = ..., inplace: Literal[False] = ... + self, labels, *, axis: Axis = ..., inplace: Literal[False] = ... ) -> Series: ... @overload - def set_axis(self, labels, axis: Axis, inplace: Literal[True]) -> None: - ... - - @overload - def set_axis(self, labels, *, inplace: Literal[True]) -> None: + def set_axis(self, labels, *, axis: Axis = ..., inplace: Literal[True]) -> None: ... @overload - def set_axis(self, labels, axis: Axis = ..., inplace: bool = ...) -> Series | None: + def set_axis( + self, labels, *, axis: Axis = ..., inplace: bool = ... + ) -> Series | None: ... + # error: Signature of "set_axis" incompatible with supertype "NDFrame" @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "labels"]) @Appender( """ @@ -4861,7 +4961,9 @@ def set_axis(self, labels, axis: Axis = ..., inplace: bool = ...) -> Series | No see_also_sub="", ) @Appender(NDFrame.set_axis.__doc__) - def set_axis(self, labels, axis: Axis = 0, inplace: bool = False): + def set_axis( # type: ignore[override] + self, labels, axis: Axis = 0, inplace: bool = False + ) -> Series | None: return super().set_axis(labels, axis=axis, inplace=inplace) # error: Cannot determine type of 'reindex' @@ -4887,11 +4989,11 @@ def reindex(self, *args, **kwargs) -> Series: @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: Literal[True], errors: IgnoreRaise = ..., @@ -4901,11 +5003,11 @@ def drop( @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: Literal[False] = ..., errors: IgnoreRaise = ..., @@ -4915,11 +5017,11 @@ def drop( @overload def drop( self, - labels: Hashable | list[Hashable] = ..., + labels: IndexLabel = ..., *, axis: Axis = ..., - index: Hashable | list[Hashable] = ..., - columns: Hashable | list[Hashable] = ..., + index: IndexLabel = ..., + columns: IndexLabel = ..., level: Level | None = ..., inplace: bool = ..., errors: IgnoreRaise = ..., @@ -4931,10 +5033,10 @@ def drop( @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "labels"]) def drop( # type: ignore[override] self, - labels: Hashable | list[Hashable] = None, + labels: IndexLabel = None, axis: Axis = 0, - index: Hashable | list[Hashable] = None, - columns: Hashable | list[Hashable] = None, + index: IndexLabel = None, + columns: IndexLabel = None, level: Level | None = None, inplace: bool = False, errors: IgnoreRaise = "raise", @@ -5198,22 +5300,52 @@ def pop(self, item: Hashable) -> Any: """ return super().pop(item=item) - # error: Cannot determine type of 'replace' + # error: Signature of "replace" incompatible with supertype "NDFrame" + @overload # type: ignore[override] + def replace( + self, + to_replace=..., + value=..., + *, + inplace: Literal[False] = ..., + limit: int | None = ..., + regex=..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> Series: + ... + + @overload + def replace( + self, + to_replace=..., + value=..., + *, + inplace: Literal[True], + limit: int | None = ..., + regex=..., + method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = ..., + ) -> None: + ... + + # error: Signature of "replace" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "to_replace", "value"] + ) @doc( - NDFrame.replace, # type: ignore[has-type] + NDFrame.replace, klass=_shared_doc_kwargs["klass"], inplace=_shared_doc_kwargs["inplace"], replace_iloc=_shared_doc_kwargs["replace_iloc"], ) - def replace( + def replace( # type: ignore[override] self, to_replace=None, value=lib.no_default, - inplace=False, - limit=None, + inplace: bool = False, + limit: int | None = None, regex=False, method: Literal["pad", "ffill", "bfill"] | lib.NoDefault = lib.no_default, - ): + ) -> Series | None: return super().replace( to_replace=to_replace, value=value, @@ -5530,8 +5662,10 @@ def _convert_dtypes( return result # error: Cannot determine type of 'isna' + # error: Return type "Series" of "isna" incompatible with return type "ndarray + # [Any, dtype[bool_]]" in supertype "IndexOpsMixin" @doc(NDFrame.isna, klass=_shared_doc_kwargs["klass"]) # type: ignore[has-type] - def isna(self) -> Series: + def isna(self) -> Series: # type: ignore[override] return NDFrame.isna(self) # error: Cannot determine type of 'isna' @@ -5555,8 +5689,22 @@ def notnull(self) -> Series: """ return super().notnull() + @overload + def dropna( + self, *, axis: Axis = ..., inplace: Literal[False] = ..., how: str | None = ... + ) -> Series: + ... + + @overload + def dropna( + self, *, axis: Axis = ..., inplace: Literal[True], how: str | None = ... + ) -> None: + ... + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) - def dropna(self, axis=0, inplace=False, how=None): + def dropna( + self, axis: Axis = 0, inplace: bool = False, how: str | None = None + ) -> Series | None: """ Return a new Series with missing values removed. @@ -5638,11 +5786,9 @@ def dropna(self, axis=0, inplace=False, how=None): else: return result else: - if inplace: - # do nothing - pass - else: + if not inplace: return self.copy() + return None # ---------------------------------------------------------------------- # Time series-oriented methods @@ -5755,25 +5901,93 @@ def to_period(self, freq=None, copy=True) -> Series: self, method="to_period" ) - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + @overload def ffill( - self: Series, + self, + *, + axis: None | Axis = ..., + inplace: Literal[False] = ..., + limit: None | int = ..., + downcast=..., + ) -> Series: + ... + + @overload + def ffill( + self, + *, + axis: None | Axis = ..., + inplace: Literal[True], + limit: None | int = ..., + downcast=..., + ) -> None: + ... + + @overload + def ffill( + self, + *, + axis: None | Axis = ..., + inplace: bool = ..., + limit: None | int = ..., + downcast=..., + ) -> Series | None: + ... + + # error: Signature of "ffill" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def ffill( # type: ignore[override] + self, axis: None | Axis = None, inplace: bool = False, limit: None | int = None, downcast=None, ) -> Series | None: - return super().ffill(axis, inplace, limit, downcast) + return super().ffill(axis=axis, inplace=inplace, limit=limit, downcast=downcast) - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + @overload def bfill( - self: Series, + self, + *, + axis: None | Axis = ..., + inplace: Literal[False] = ..., + limit: None | int = ..., + downcast=..., + ) -> Series: + ... + + @overload + def bfill( + self, + *, + axis: None | Axis = ..., + inplace: Literal[True], + limit: None | int = ..., + downcast=..., + ) -> None: + ... + + @overload + def bfill( + self, + *, + axis: None | Axis = ..., + inplace: bool = ..., + limit: None | int = ..., + downcast=..., + ) -> Series | None: + ... + + # error: Signature of "bfill" incompatible with supertype "NDFrame" + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def bfill( # type: ignore[override] + self, axis: None | Axis = None, inplace: bool = False, limit: None | int = None, downcast=None, ) -> Series | None: - return super().bfill(axis, inplace, limit, downcast) + return super().bfill(axis=axis, inplace=inplace, limit=limit, downcast=downcast) @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "lower", "upper"] @@ -5812,35 +6026,137 @@ def interpolate( **kwargs, ) + @overload + def where( + self, + cond, + other=..., + *, + inplace: Literal[False] = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> Series: + ... + + @overload + def where( + self, + cond, + other=..., + *, + inplace: Literal[True], + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> None: + ... + + @overload + def where( + self, + cond, + other=..., + *, + inplace: bool = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> Series | None: + ... + + # error: Signature of "where" incompatible with supertype "NDFrame" @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "cond", "other"] ) - def where( + def where( # type: ignore[override] self, cond, other=lib.no_default, - inplace=False, + inplace: bool = False, axis=None, level=None, - errors=lib.no_default, + errors: IgnoreRaise | lib.NoDefault = lib.no_default, try_cast=lib.no_default, - ): - return super().where(cond, other, inplace, axis, level, errors, try_cast) + ) -> Series | None: + return super().where( + cond, + other, + inplace=inplace, + axis=axis, + level=level, + errors=errors, + try_cast=try_cast, + ) + + @overload + def mask( + self, + cond, + other=..., + *, + inplace: Literal[False] = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> Series: + ... + + @overload + def mask( + self, + cond, + other=..., + *, + inplace: Literal[True], + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> None: + ... + @overload + def mask( + self, + cond, + other=..., + *, + inplace: bool = ..., + axis=..., + level=..., + errors: IgnoreRaise | lib.NoDefault = ..., + try_cast=..., + ) -> Series | None: + ... + + # error: Signature of "mask" incompatible with supertype "NDFrame" @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "cond", "other"] ) - def mask( + def mask( # type: ignore[override] self, cond, other=np.nan, - inplace=False, + inplace: bool = False, axis=None, level=None, - errors=lib.no_default, + errors: IgnoreRaise | lib.NoDefault = lib.no_default, try_cast=lib.no_default, - ): - return super().mask(cond, other, inplace, axis, level, errors, try_cast) + ) -> Series | None: + return super().mask( + cond, + other, + inplace=inplace, + axis=axis, + level=level, + errors=errors, + try_cast=try_cast, + ) # ---------------------------------------------------------------------- # Add index diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 497523211f2d8..6d497f7d9bb94 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -564,7 +564,7 @@ class DataFrameFormatter: def __init__( self, frame: DataFrame, - columns: Sequence[str] | None = None, + columns: Sequence[Hashable] | None = None, col_space: ColspaceArgType | None = None, header: bool | Sequence[str] = True, index: bool = True, @@ -686,7 +686,7 @@ def _initialize_justify(self, justify: str | None) -> str: else: return justify - def _initialize_columns(self, columns: Sequence[str] | None) -> Index: + def _initialize_columns(self, columns: Sequence[Hashable] | None) -> Index: if columns is not None: cols = ensure_index(columns) self.frame = self.frame[cols]