@@ -787,11 +787,17 @@ def na_op(x, y):
787
787
788
788
return result
789
789
790
- fill_int = lambda x : x . fillna ( 0 )
790
+ fill_int = lambda x : x
791
791
792
792
def fill_bool (x , left = None ):
793
793
# if `left` is specifically not-boolean, we do not cast to bool
794
- x = x .fillna (False )
794
+ if x .dtype .kind in ["c" , "f" , "O" ]:
795
+ # dtypes that can hold NA
796
+ mask = isna (x )
797
+ if mask .any ():
798
+ x = x .astype (object )
799
+ x [mask ] = False
800
+
795
801
if left is None or is_bool_dtype (left .dtype ):
796
802
x = x .astype (bool )
797
803
return x
@@ -814,40 +820,35 @@ def wrapper(self, other):
814
820
# Defer to DataFrame implementation; fail early
815
821
return NotImplemented
816
822
817
- elif should_extension_dispatch (self , other ):
818
- lvalues = extract_array (self , extract_numpy = True )
819
- rvalues = extract_array (other , extract_numpy = True )
823
+ other = lib .item_from_zerodim (other )
824
+ if is_list_like (other ) and not hasattr (other , "dtype" ):
825
+ # e.g. list, tuple
826
+ other = construct_1d_object_array_from_listlike (other )
827
+
828
+ lvalues = extract_array (self , extract_numpy = True )
829
+ rvalues = extract_array (other , extract_numpy = True )
830
+
831
+ if should_extension_dispatch (self , rvalues ):
820
832
res_values = dispatch_to_extension_op (op , lvalues , rvalues )
821
- result = self ._constructor (res_values , index = self .index , name = res_name )
822
- return finalizer (result )
823
833
824
- elif isinstance (other , (ABCSeries , ABCIndexClass )):
825
- is_other_int_dtype = is_integer_dtype (other .dtype )
826
- other = other if is_other_int_dtype else fill_bool (other , self )
834
+ else :
835
+ if isinstance (rvalues , (ABCSeries , ABCIndexClass , np .ndarray )):
836
+ is_other_int_dtype = is_integer_dtype (rvalues .dtype )
837
+ rvalues = rvalues if is_other_int_dtype else fill_bool (rvalues , lvalues )
827
838
828
- elif is_list_like (other ):
829
- # list, tuple, np.ndarray
830
- if not isinstance (other , np .ndarray ):
831
- other = construct_1d_object_array_from_listlike (other )
839
+ else :
840
+ # i.e. scalar
841
+ is_other_int_dtype = lib .is_integer (rvalues )
832
842
833
- is_other_int_dtype = is_integer_dtype ( other . dtype )
834
- other = type ( self )( other )
835
- other = other if is_other_int_dtype else fill_bool ( other , self )
843
+ # For int vs int `^`, `|`, `&` are bitwise operators and return
844
+ # integer dtypes. Otherwise these are boolean ops
845
+ filler = fill_int if is_self_int_dtype and is_other_int_dtype else fill_bool
836
846
837
- else :
838
- # i.e. scalar
839
- is_other_int_dtype = lib .is_integer (other )
840
-
841
- # TODO: use extract_array once we handle EA correctly, see GH#27959
842
- ovalues = lib .values_from_object (other )
843
-
844
- # For int vs int `^`, `|`, `&` are bitwise operators and return
845
- # integer dtypes. Otherwise these are boolean ops
846
- filler = fill_int if is_self_int_dtype and is_other_int_dtype else fill_bool
847
- res_values = na_op (self .values , ovalues )
848
- unfilled = self ._constructor (res_values , index = self .index , name = res_name )
849
- filled = filler (unfilled )
850
- return finalizer (filled )
847
+ res_values = na_op (lvalues , rvalues )
848
+ res_values = filler (res_values )
849
+
850
+ result = self ._constructor (res_values , index = self .index , name = res_name )
851
+ return finalizer (result )
851
852
852
853
wrapper .__name__ = op_name
853
854
return wrapper
0 commit comments