diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index 6b03e76a1d691..bb6f7216eae01 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -421,8 +421,27 @@ def nanany(values, axis=None, skipna: bool = True, mask=None): >>> nanops.nanany(s) False """ - values, _, _, _, _ = _get_values(values, skipna, fill_value=False, mask=mask) - return values.any(axis) + values, _, dtype, _, _ = _get_values(values, skipna, fill_value=False, mask=mask) + + # GH #12863 + # Checking if the `axis` is None because numpy + # doesn't handle ``any`` and ``all`` on + # object arrays correctly. see + # https://github.com/numpy/numpy/issues/4352 + + # TODO: Find a less code-smelly way of doing this + if is_object_dtype(dtype) and axis is None: + output = values.any() + else: + output = values.any(axis) + + if isinstance(output, bool): + return output + + try: + return any(values) + except ValueError: + return values.any() def nanall(values, axis=None, skipna: bool = True, mask=None): @@ -453,8 +472,27 @@ def nanall(values, axis=None, skipna: bool = True, mask=None): >>> nanops.nanall(s) False """ - values, _, _, _, _ = _get_values(values, skipna, fill_value=True, mask=mask) - return values.all(axis) + values, _, dtype, _, _ = _get_values(values, skipna, fill_value=True, mask=mask) + + # GH #12863 + # Checking if the `axis` is None because numpy + # doesn't handle ``any`` and ``all`` on + # object arrays correctly. see + # https://github.com/numpy/numpy/issues/4352 + + # TODO: Find a less code-smelly way of doing this + if is_object_dtype(dtype) and axis is None: + output = values.all() + else: + output = values.all(axis) + + if isinstance(output, bool): + return output + + try: + return all(values) + except ValueError: + return values.all() @disallow("M8") diff --git a/pandas/tests/reductions/test_reductions.py b/pandas/tests/reductions/test_reductions.py index 7400b049961d5..3bc8ec7222b04 100644 --- a/pandas/tests/reductions/test_reductions.py +++ b/pandas/tests/reductions/test_reductions.py @@ -811,19 +811,24 @@ def test_all_any(self): assert not bool_series.all() assert bool_series.any() - # Alternative types, with implicit 'object' dtype. - s = Series(["abc", True]) - assert "abc" == s.any() # 'abc' || True => 'abc' - def test_all_any_params(self): # Check skipna, with implicit 'object' dtype. s1 = Series([np.nan, True]) s2 = Series([np.nan, False]) - assert s1.all(skipna=False) # nan && True => True + + # GH #12863 assert s1.all(skipna=True) - assert np.isnan(s2.any(skipna=False)) # nan || False => nan + assert s1.any(skipna=True) + + assert s1.all(skipna=False) + assert s1.any(skipna=False) + + assert not s2.all(skipna=True) assert not s2.any(skipna=True) + assert not s2.all(skipna=False) + assert s2.any(skipna=False) + # Check level. s = pd.Series([False, False, True, True, False, True], index=[0, 0, 1, 1, 2, 2]) tm.assert_series_equal(s.all(level=0), Series([False, True, False])) @@ -841,6 +846,18 @@ def test_all_any_params(self): with pytest.raises(NotImplementedError): s.all(bool_only=True) + def test_all_any_object_dtype(self): + # GH 12863 + + s1 = Series(["abc", True]) + s2 = Series(["abc", False]) + + assert s1.all() + assert s1.any() + + assert not s2.all() + assert s2.any() + def test_timedelta64_analytics(self): # index min/max diff --git a/pandas/tests/series/test_apply.py b/pandas/tests/series/test_apply.py index a4c55a80a9f0f..ef16fd98c6d46 100644 --- a/pandas/tests/series/test_apply.py +++ b/pandas/tests/series/test_apply.py @@ -390,8 +390,8 @@ def test_non_callable_aggregates(self): ("sum", "abc"), ("max", "c"), ("min", "a"), - ("all", "c"), # see GH12863 - ("any", "a"), + ("all", True), + ("any", True), ], ), ), diff --git a/pandas/tests/test_nanops.py b/pandas/tests/test_nanops.py index 2c5d028ebe42e..6571a80c50a0a 100644 --- a/pandas/tests/test_nanops.py +++ b/pandas/tests/test_nanops.py @@ -270,6 +270,10 @@ def _badobj_wrap(self, value, func, allow_complex=True, **kwargs): value = value.astype("f8") return func(value, **kwargs) + # GH #12863 + # Disabled until https://github.com/numpy/numpy/issues/4352 + # is fixed + @pytest.mark.xfail(reason="disabled") @pytest.mark.parametrize( "nan_op,np_op", [(nanops.nanany, np.any), (nanops.nanall, np.all)] )