diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 977186d808e81..f2650a64d2c59 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -414,6 +414,7 @@ Other API changes - Index set operations (like union or intersection) will now ignore the dtype of an empty ``RangeIndex`` or empty ``Index`` with object dtype when determining the dtype of the resulting Index (:issue:`60797`) +- Numpy functions like ``np.isinf`` that return a bool dtype when called on a :class:`Index` object now return a bool-dtype :class:`Index` instead of ``np.ndarray`` (:issue:`52676`) .. --------------------------------------------------------------------------- .. _whatsnew_300.deprecations: diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 0b719ae21d5b9..fb395f4f7bb1a 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -965,12 +965,8 @@ def __array_wrap__(self, result, context=None, return_scalar=False): Gets called after a ufunc and other functions e.g. np.split. """ result = lib.item_from_zerodim(result) - if (not isinstance(result, Index) and is_bool_dtype(result.dtype)) or np.ndim( - result - ) > 1: - # exclude Index to avoid warning from is_bool_dtype deprecation; - # in the Index case it doesn't matter which path we go down. - # reached in plotting tests with e.g. np.nonzero(index) + if np.ndim(result) > 1: + # Reached in plotting tests with e.g. np.nonzero(index) return result return Index(result, name=self.name) diff --git a/pandas/tests/indexes/test_numpy_compat.py b/pandas/tests/indexes/test_numpy_compat.py index ace78d77350cb..86d0ca1280596 100644 --- a/pandas/tests/indexes/test_numpy_compat.py +++ b/pandas/tests/indexes/test_numpy_compat.py @@ -2,6 +2,7 @@ import pytest from pandas import ( + BooleanDtype, CategoricalIndex, DatetimeIndex, Index, @@ -14,7 +15,6 @@ is_complex_dtype, is_numeric_dtype, ) -from pandas.core.arrays import BooleanArray from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin @@ -111,11 +111,10 @@ def test_numpy_ufuncs_other(index, func): if func in (np.isfinite, np.isinf, np.isnan): # numpy 1.18 changed isinf and isnan to not raise on dt64/td64 result = func(index) - assert isinstance(result, np.ndarray) out = np.empty(index.shape, dtype=bool) func(index, out=out) - tm.assert_numpy_array_equal(out, result) + tm.assert_index_equal(Index(out), result) else: with tm.external_error_raised(TypeError): func(index) @@ -129,19 +128,20 @@ def test_numpy_ufuncs_other(index, func): ): # Results in bool array result = func(index) + assert isinstance(result, Index) if not isinstance(index.dtype, np.dtype): # e.g. Int64 we expect to get BooleanArray back - assert isinstance(result, BooleanArray) + assert isinstance(result.dtype, BooleanDtype) else: - assert isinstance(result, np.ndarray) + assert isinstance(result.dtype, np.dtype) out = np.empty(index.shape, dtype=bool) func(index, out=out) if not isinstance(index.dtype, np.dtype): - tm.assert_numpy_array_equal(out, result._data) + tm.assert_index_equal(result, Index(out, dtype="boolean")) else: - tm.assert_numpy_array_equal(out, result) + tm.assert_index_equal(result, Index(out)) elif len(index) == 0: pass