diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 99d9568926df4..c3d21acbe9e4d 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -2,7 +2,6 @@ from datetime import datetime from itertools import zip_longest import operator -from textwrap import dedent from typing import ( TYPE_CHECKING, Any, @@ -30,7 +29,7 @@ from pandas.compat import set_function_name from pandas.compat.numpy import function as nv from pandas.errors import DuplicateLabelError, InvalidIndexError -from pandas.util._decorators import Appender, Substitution, cache_readonly, doc +from pandas.util._decorators import Appender, cache_readonly, doc from pandas.core.dtypes import concat as _concat from pandas.core.dtypes.cast import ( @@ -61,6 +60,7 @@ is_signed_integer_dtype, is_timedelta64_dtype, is_unsigned_integer_dtype, + needs_i8_conversion, pandas_dtype, validate_all_hashable, ) @@ -5447,28 +5447,61 @@ def _add_numeric_methods(cls): cls._add_numeric_methods_unary() cls._add_numeric_methods_binary() - @classmethod - def _add_logical_methods(cls): - """ - Add in logical methods. + def any(self, *args, **kwargs): """ - _doc = """ - %(desc)s + Return whether any element is Truthy. Parameters ---------- *args - These parameters will be passed to numpy.%(outname)s. + These parameters will be passed to numpy.any. **kwargs - These parameters will be passed to numpy.%(outname)s. + These parameters will be passed to numpy.any. Returns ------- - %(outname)s : bool or array_like (if axis is specified) - A single element array_like may be converted to bool.""" + any : bool or array_like (if axis is specified) + A single element array_like may be converted to bool. - _index_shared_docs["index_all"] = dedent( - """ + See Also + -------- + Index.all : Return whether all elements are True. + Series.all : Return whether all elements are True. + + Notes + ----- + Not a Number (NaN), positive infinity and negative infinity + evaluate to True because these are not equal to zero. + + Examples + -------- + >>> index = pd.Index([0, 1, 2]) + >>> index.any() + True + + >>> index = pd.Index([0, 0, 0]) + >>> index.any() + False + """ + # FIXME: docstr inaccurate, args/kwargs not passed + self._maybe_disable_logical_methods("any") + return np.any(self.values) + + def all(self): + """ + Return whether all elements are Truthy. + + Parameters + ---------- + *args + These parameters will be passed to numpy.all. + **kwargs + These parameters will be passed to numpy.all. + + Returns + ------- + all : bool or array_like (if axis is specified) + A single element array_like may be converted to bool. See Also -------- @@ -5507,65 +5540,24 @@ def _add_logical_methods(cls): >>> pd.Index([0, 0, 0]).any() False """ - ) - - _index_shared_docs["index_any"] = dedent( - """ - - See Also - -------- - Index.all : Return whether all elements are True. - Series.all : Return whether all elements are True. + # FIXME: docstr inaccurate, args/kwargs not passed - Notes - ----- - Not a Number (NaN), positive infinity and negative infinity - evaluate to True because these are not equal to zero. + self._maybe_disable_logical_methods("all") + return np.all(self.values) - Examples - -------- - >>> index = pd.Index([0, 1, 2]) - >>> index.any() - True - - >>> index = pd.Index([0, 0, 0]) - >>> index.any() - False + def _maybe_disable_logical_methods(self, opname: str_t): """ - ) - - def _make_logical_function(name: str_t, desc: str_t, f): - @Substitution(outname=name, desc=desc) - @Appender(_index_shared_docs["index_" + name]) - @Appender(_doc) - def logical_func(self, *args, **kwargs): - result = f(self.values) - if ( - isinstance(result, (np.ndarray, ABCSeries, Index)) - and result.ndim == 0 - ): - # return NumPy type - return result.dtype.type(result.item()) - else: # pragma: no cover - return result - - logical_func.__name__ = name - return logical_func - - cls.all = _make_logical_function( - "all", "Return whether all elements are True.", np.all - ) - cls.any = _make_logical_function( - "any", "Return whether any element is True.", np.any - ) - - @classmethod - def _add_logical_methods_disabled(cls): + raise if this Index subclass does not support any or all. """ - Add in logical methods to disable. - """ - cls.all = make_invalid_op("all") - cls.any = make_invalid_op("any") + if ( + isinstance(self, ABCMultiIndex) + or needs_i8_conversion(self.dtype) + or is_interval_dtype(self.dtype) + or is_categorical_dtype(self.dtype) + or is_float_dtype(self.dtype) + ): + # This call will raise + make_invalid_op(opname)(self) @property def shape(self): @@ -5579,7 +5571,6 @@ def shape(self): Index._add_numeric_methods() -Index._add_logical_methods() def ensure_index_from_sequences(sequences, names=None): diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index d3167189dbcc6..8038bc6bf1c72 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -721,6 +721,3 @@ def _wrap_joined_index( name = get_op_result_name(self, other) cat = self._data._from_backing_data(joined) return type(self)._simple_new(cat, name=name) - - -CategoricalIndex._add_logical_methods_disabled() diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 67b71ce63a6e3..8255a4f6875a6 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -871,9 +871,6 @@ def indexer_between_time( return mask.nonzero()[0] -DatetimeIndex._add_logical_methods_disabled() - - def date_range( start=None, end=None, diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index efb8a3e850b1a..93117fbc22752 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -1120,9 +1120,6 @@ def __ge__(self, other): return Index.__ge__(self, other) -IntervalIndex._add_logical_methods_disabled() - - def _is_valid_endpoint(endpoint) -> bool: """ Helper for interval_range to check if start/end are valid types. diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 7e2bad3e4bf93..0604f70316cfb 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -3723,7 +3723,6 @@ def _add_numeric_methods_disabled(cls): MultiIndex._add_numeric_methods_disabled() MultiIndex._add_numeric_methods_add_sub_disabled() -MultiIndex._add_logical_methods_disabled() def sparsify_labels(label_list, start: int = 0, sentinel=""): diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index 34bbaca06cc08..60a206a5344de 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -276,7 +276,6 @@ def _can_union_without_object_cast(self, other) -> bool: Int64Index._add_numeric_methods() -Int64Index._add_logical_methods() _uint64_descr_args = dict( klass="UInt64Index", ltype="unsigned integer", dtype="uint64", extra="" @@ -323,7 +322,6 @@ def _can_union_without_object_cast(self, other) -> bool: UInt64Index._add_numeric_methods() -UInt64Index._add_logical_methods() _float64_descr_args = dict( klass="Float64Index", dtype="float64", ltype="float", extra="" @@ -430,4 +428,3 @@ def _can_union_without_object_cast(self, other) -> bool: Float64Index._add_numeric_methods() -Float64Index._add_logical_methods_disabled() diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index adf7a75b33b38..ce2839ab9a8e1 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -719,9 +719,6 @@ def memory_usage(self, deep: bool = False) -> int: return result -PeriodIndex._add_logical_methods_disabled() - - def period_range( start=None, end=None, periods=None, freq=None, name=None ) -> PeriodIndex: diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 90b713e8f09a9..14146503afd8d 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -804,10 +804,10 @@ def __floordiv__(self, other): # -------------------------------------------------------------------- # Reductions - def all(self) -> bool: + def all(self, *args, **kwargs) -> bool: return 0 not in self._range - def any(self) -> bool: + def any(self, *args, **kwargs) -> bool: return any(self._range) # -------------------------------------------------------------------- diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 2a7c624b430ed..302fead8c8b0c 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -261,9 +261,6 @@ def inferred_type(self) -> str: return "timedelta64" -TimedeltaIndex._add_logical_methods_disabled() - - def timedelta_range( start=None, end=None, periods=None, freq=None, name=None, closed=None ) -> TimedeltaIndex: