Skip to content

REF: move methods from base to Index #52447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 2 additions & 114 deletions pandas/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

from pandas._libs import lib
from pandas._typing import (
Axis,
AxisInt,
DtypeObj,
IndexLabel,
Expand Down Expand Up @@ -588,7 +587,8 @@ def to_numpy(
values = np.asarray(values, dtype=dtype)
else:
values = values.copy()
values[np.asanyarray(self.isna())] = na_value

values[np.asanyarray(isna(self))] = na_value

result = np.asarray(values, dtype=dtype)

Expand All @@ -608,50 +608,6 @@ def to_numpy(
def empty(self) -> bool:
return not self.size

def max(self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs):
"""
Return the maximum value of the Index.

Parameters
----------
axis : int, optional
For compatibility with NumPy. Only 0 or None are allowed.
skipna : bool, default True
Exclude NA/null values when showing the result.
*args, **kwargs
Additional arguments and keywords for compatibility with NumPy.

Returns
-------
scalar
Maximum value.

See Also
--------
Index.min : Return the minimum value in an Index.
Series.max : Return the maximum value in a Series.
DataFrame.max : Return the maximum values in a DataFrame.

Examples
--------
>>> idx = pd.Index([3, 2, 1])
>>> idx.max()
3

>>> idx = pd.Index(['c', 'b', 'a'])
>>> idx.max()
'c'

For a MultiIndex, the maximum is determined lexicographically.

>>> idx = pd.MultiIndex.from_product([('a', 'b'), (2, 1)])
>>> idx.max()
('b', 2)
"""
nv.validate_minmax_axis(axis)
nv.validate_max(args, kwargs)
return nanops.nanmax(self._values, skipna=skipna)

@doc(op="max", oppose="min", value="largest")
def argmax(
self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs
Expand Down Expand Up @@ -722,50 +678,6 @@ def argmax(
delegate, skipna=skipna
)

def min(self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs):
"""
Return the minimum value of the Index.

Parameters
----------
axis : {None}
Dummy argument for consistency with Series.
skipna : bool, default True
Exclude NA/null values when showing the result.
*args, **kwargs
Additional arguments and keywords for compatibility with NumPy.

Returns
-------
scalar
Minimum value.

See Also
--------
Index.max : Return the maximum value of the object.
Series.min : Return the minimum value in a Series.
DataFrame.min : Return the minimum values in a DataFrame.

Examples
--------
>>> idx = pd.Index([3, 2, 1])
>>> idx.min()
1

>>> idx = pd.Index(['c', 'b', 'a'])
>>> idx.min()
'a'

For a MultiIndex, the minimum is determined lexicographically.

>>> idx = pd.MultiIndex.from_product([('a', 'b'), (2, 1)])
>>> idx.min()
('a', 1)
"""
nv.validate_minmax_axis(axis)
nv.validate_min(args, kwargs)
return nanops.nanmin(self._values, skipna=skipna)

@doc(argmax, op="min", oppose="max", value="smallest")
def argmin(
self, axis: AxisInt | None = None, skipna: bool = True, *args, **kwargs
Expand Down Expand Up @@ -859,30 +771,6 @@ def hasnans(self) -> bool:
# has no attribute "any"
return bool(isna(self).any()) # type: ignore[union-attr]

def isna(self) -> npt.NDArray[np.bool_]:
return isna(self._values)

def _reduce(
self,
op,
name: str,
*,
axis: Axis = 0,
skipna: bool = True,
numeric_only=None,
filter_type=None,
**kwds,
):
"""
Perform the reduction type operation if we can.
"""
func = getattr(self, name, None)
if func is None:
raise TypeError(
f"{type(self).__name__} cannot perform the operation {name}"
)
return func(skipna=skipna, **kwds)

@final
def _map_values(self, mapper, na_action=None, convert: bool = True):
"""
Expand Down
86 changes: 82 additions & 4 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@

from pandas.core import (
arraylike,
nanops,
ops,
)
from pandas.core.accessor import CachedAccessor
Expand Down Expand Up @@ -6984,8 +6985,46 @@ def argmax(self, axis=None, skipna: bool = True, *args, **kwargs) -> int:
return -1
return super().argmax(skipna=skipna)

@doc(IndexOpsMixin.min)
def min(self, axis=None, skipna: bool = True, *args, **kwargs):
"""
Return the minimum value of the Index.

Parameters
----------
axis : {None}
Dummy argument for consistency with Series.
skipna : bool, default True
Exclude NA/null values when showing the result.
*args, **kwargs
Additional arguments and keywords for compatibility with NumPy.

Returns
-------
scalar
Minimum value.

See Also
--------
Index.max : Return the maximum value of the object.
Series.min : Return the minimum value in a Series.
DataFrame.min : Return the minimum values in a DataFrame.

Examples
--------
>>> idx = pd.Index([3, 2, 1])
>>> idx.min()
1

>>> idx = pd.Index(['c', 'b', 'a'])
>>> idx.min()
'a'

For a MultiIndex, the minimum is determined lexicographically.

>>> idx = pd.MultiIndex.from_product([('a', 'b'), (2, 1)])
>>> idx.min()
('a', 1)
"""
nv.validate_min(args, kwargs)
nv.validate_minmax_axis(axis)

Expand All @@ -7007,10 +7046,49 @@ def min(self, axis=None, skipna: bool = True, *args, **kwargs):
if not self._is_multi and not isinstance(self._values, np.ndarray):
return self._values._reduce(name="min", skipna=skipna)

return super().min(skipna=skipna)
return nanops.nanmin(self._values, skipna=skipna)

@doc(IndexOpsMixin.max)
def max(self, axis=None, skipna: bool = True, *args, **kwargs):
"""
Return the maximum value of the Index.

Parameters
----------
axis : int, optional
For compatibility with NumPy. Only 0 or None are allowed.
skipna : bool, default True
Exclude NA/null values when showing the result.
*args, **kwargs
Additional arguments and keywords for compatibility with NumPy.

Returns
-------
scalar
Maximum value.

See Also
--------
Index.min : Return the minimum value in an Index.
Series.max : Return the maximum value in a Series.
DataFrame.max : Return the maximum values in a DataFrame.

Examples
--------
>>> idx = pd.Index([3, 2, 1])
>>> idx.max()
3

>>> idx = pd.Index(['c', 'b', 'a'])
>>> idx.max()
'c'

For a MultiIndex, the maximum is determined lexicographically.

>>> idx = pd.MultiIndex.from_product([('a', 'b'), (2, 1)])
>>> idx.max()
('b', 2)
"""

nv.validate_max(args, kwargs)
nv.validate_minmax_axis(axis)

Expand All @@ -7032,7 +7110,7 @@ def max(self, axis=None, skipna: bool = True, *args, **kwargs):
if not self._is_multi and not isinstance(self._values, np.ndarray):
return self._values._reduce(name="max", skipna=skipna)

return super().max(skipna=skipna)
return nanops.nanmax(self._values, skipna=skipna)

# --------------------------------------------------------------------

Expand Down
17 changes: 7 additions & 10 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,10 @@ def wrapper(self):
# Series class


# error: Definition of "max" in base class "IndexOpsMixin" is incompatible with
# definition in base class "NDFrame"
# error: Definition of "min" in base class "IndexOpsMixin" is incompatible with
# error: Cannot override final attribute "ndim" (previously declared in base
# class "NDFrame")
# error: Cannot override final attribute "size" (previously declared in base
# class "NDFrame")
# definition in base class "NDFrame"
class Series(base.IndexOpsMixin, NDFrame): # type: ignore[misc]
"""
Expand Down Expand Up @@ -5395,10 +5396,8 @@ 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: # type: ignore[override]
def isna(self) -> Series:
return NDFrame.isna(self)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return super().isna()?

Same question below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoiding super bc i always have to check which parent class it refers to


# error: Cannot determine type of 'isna'
Expand Down Expand Up @@ -6092,8 +6091,7 @@ def all(
)

@doc(make_doc("min", ndim=1))
# error: Signature of "min" incompatible with supertype "IndexOpsMixin"
def min( # type: ignore[override]
def min(
self,
axis: Axis | None = 0,
skipna: bool = True,
Expand All @@ -6103,8 +6101,7 @@ def min( # type: ignore[override]
return NDFrame.min(self, axis, skipna, numeric_only, **kwargs)

@doc(make_doc("max", ndim=1))
# error: Signature of "max" incompatible with supertype "IndexOpsMixin"
def max( # type: ignore[override]
def max(
self,
axis: Axis | None = 0,
skipna: bool = True,
Expand Down