Skip to content

Commit 20474d5

Browse files
BUG: fix boolean array skipna=False for .any() and .all() (#33284)
Co-authored-by: Joris Van den Bossche <[email protected]>
1 parent b7e786e commit 20474d5

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

doc/source/whatsnew/v1.1.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ Missing
452452
^^^^^^^
453453

454454
- Calling :meth:`fillna` on an empty Series now correctly returns a shallow copied object. The behaviour is now consistent with :class:`Index`, :class:`DataFrame` and a non-empty :class:`Series` (:issue:`32543`).
455-
455+
- Bug in :meth:`~Series.any` and :meth:`~Series.all` incorrectly returning ``<NA>`` for all ``False`` or all ``True`` values using the nulllable boolean dtype and with ``skipna=False`` (:issue:`33253`)
456456

457457
MultiIndex
458458
^^^^^^^^^^

pandas/core/arrays/boolean.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ def any(self, skipna: bool = True, **kwargs):
520520
if skipna:
521521
return result
522522
else:
523-
if result or len(self) == 0:
523+
if result or len(self) == 0 or not self._mask.any():
524524
return result
525525
else:
526526
return self.dtype.na_value
@@ -587,7 +587,7 @@ def all(self, skipna: bool = True, **kwargs):
587587
if skipna:
588588
return result
589589
else:
590-
if not result or len(self) == 0:
590+
if not result or len(self) == 0 or not self._mask.any():
591591
return result
592592
else:
593593
return self.dtype.na_value

pandas/tests/arrays/boolean/test_reduction.py

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ def data():
1919
([False, pd.NA], False, False, pd.NA, False),
2020
([pd.NA], False, True, pd.NA, pd.NA),
2121
([], False, True, False, True),
22+
# GH-33253: all True / all False values buggy with skipna=False
23+
([True, True], True, True, True, True),
24+
([False, False], False, False, False, False),
2225
],
2326
)
2427
def test_any_all(values, exp_any, exp_all, exp_any_noskip, exp_all_noskip):

pandas/tests/reductions/test_reductions.py

+24
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,30 @@ def test_all_any_params(self):
891891
with pytest.raises(NotImplementedError):
892892
s.all(bool_only=True)
893893

894+
def test_all_any_boolean(self):
895+
# Check skipna, with boolean type
896+
s1 = Series([pd.NA, True], dtype="boolean")
897+
s2 = Series([pd.NA, False], dtype="boolean")
898+
assert s1.all(skipna=False) is pd.NA # NA && True => NA
899+
assert s1.all(skipna=True)
900+
assert s2.any(skipna=False) is pd.NA # NA || False => NA
901+
assert not s2.any(skipna=True)
902+
903+
# GH-33253: all True / all False values buggy with skipna=False
904+
s3 = Series([True, True], dtype="boolean")
905+
s4 = Series([False, False], dtype="boolean")
906+
assert s3.all(skipna=False)
907+
assert not s4.any(skipna=False)
908+
909+
# Check level TODO(GH-33449) result should also be boolean
910+
s = pd.Series(
911+
[False, False, True, True, False, True],
912+
index=[0, 0, 1, 1, 2, 2],
913+
dtype="boolean",
914+
)
915+
tm.assert_series_equal(s.all(level=0), Series([False, True, False]))
916+
tm.assert_series_equal(s.any(level=0), Series([False, True, True]))
917+
894918
def test_timedelta64_analytics(self):
895919

896920
# index min/max

0 commit comments

Comments
 (0)