@@ -184,6 +184,9 @@ class BooleanArray(ExtensionArray, ExtensionOpsMixin):
184184 represented by 2 numpy arrays: a boolean array with the data and
185185 a boolean array with the mask (True indicating missing).
186186
187+ BooleanArray implements Kleene logic (sometimes called three-value
188+ logic) for logical operations. See :ref:`boolean.kleene` for more.
189+
187190 To construct an BooleanArray from generic array-like input, use
188191 :func:`pandas.array` specifying ``dtype="boolean"`` (see examples
189192 below).
@@ -283,7 +286,7 @@ def __getitem__(self, item):
283286
284287 def _coerce_to_ndarray (self , dtype = None , na_value : "Scalar" = libmissing .NA ):
285288 """
286- Coerce to an ndarary of object dtype or bool dtype (if force_bool=True).
289+ Coerce to an ndarray of object dtype or bool dtype (if force_bool=True).
287290
288291 Parameters
289292 ----------
@@ -565,33 +568,40 @@ def logical_method(self, other):
565568 # Rely on pandas to unbox and dispatch to us.
566569 return NotImplemented
567570
571+ assert op .__name__ in {"or_" , "ror_" , "and_" , "rand_" , "xor" , "rxor" }
568572 other = lib .item_from_zerodim (other )
573+ other_is_booleanarray = isinstance (other , BooleanArray )
574+ other_is_scalar = lib .is_scalar (other )
569575 mask = None
570576
571- if isinstance ( other , BooleanArray ) :
577+ if other_is_booleanarray :
572578 other , mask = other ._data , other ._mask
573579 elif is_list_like (other ):
574580 other = np .asarray (other , dtype = "bool" )
575581 if other .ndim > 1 :
576582 raise NotImplementedError (
577583 "can only perform ops with 1-d structures"
578584 )
579- if len (self ) != len (other ):
580- raise ValueError ("Lengths must match to compare" )
581585 other , mask = coerce_to_array (other , copy = False )
586+ elif isinstance (other , np .bool_ ):
587+ other = other .item ()
588+
589+ if other_is_scalar and not (other is libmissing .NA or lib .is_bool (other )):
590+ raise TypeError (
591+ "'other' should be pandas.NA or a bool. Got {} instead." .format (
592+ type (other ).__name__
593+ )
594+ )
582595
583- # numpy will show a DeprecationWarning on invalid elementwise
584- # comparisons, this will raise in the future
585- with warnings .catch_warnings ():
586- warnings .filterwarnings ("ignore" , "elementwise" , FutureWarning )
587- with np .errstate (all = "ignore" ):
588- result = op (self ._data , other )
596+ if not other_is_scalar and len (self ) != len (other ):
597+ raise ValueError ("Lengths must match to compare" )
589598
590- # nans propagate
591- if mask is None :
592- mask = self ._mask
593- else :
594- mask = self ._mask | mask
599+ if op .__name__ in {"or_" , "ror_" }:
600+ result , mask = ops .kleene_or (self ._data , other , self ._mask , mask )
601+ elif op .__name__ in {"and_" , "rand_" }:
602+ result , mask = ops .kleene_and (self ._data , other , self ._mask , mask )
603+ elif op .__name__ in {"xor" , "rxor" }:
604+ result , mask = ops .kleene_xor (self ._data , other , self ._mask , mask )
595605
596606 return BooleanArray (result , mask )
597607
0 commit comments