@@ -814,6 +814,15 @@ def wrapper(self, other, axis=None):
814
814
self ._get_axis_number (axis )
815
815
816
816
res_name = get_op_result_name (self , other )
817
+ other = lib .item_from_zerodim (other )
818
+
819
+ # TODO: shouldn't we be applying finalize whenever
820
+ # not isinstance(other, ABCSeries)?
821
+ finalizer = (
822
+ lambda x : x .__finalize__ (self )
823
+ if isinstance (other , (np .ndarray , ABCIndexClass ))
824
+ else x
825
+ )
817
826
818
827
if isinstance (other , list ):
819
828
# TODO: same for tuples?
@@ -826,80 +835,60 @@ def wrapper(self, other, axis=None):
826
835
elif isinstance (other , ABCSeries ) and not self ._indexed_same (other ):
827
836
raise ValueError ("Can only compare identically-labeled Series objects" )
828
837
829
- elif is_categorical_dtype (self ):
838
+ elif (
839
+ is_list_like (other )
840
+ and len (other ) != len (self )
841
+ and not isinstance (other , frozenset )
842
+ ):
843
+ # TODO: why are we treating len-1 frozenset differently?
844
+ raise ValueError ("Lengths must match to compare" )
845
+
846
+ if is_categorical_dtype (self ):
830
847
# Dispatch to Categorical implementation; CategoricalIndex
831
848
# behavior is non-canonical GH#19513
832
849
res_values = dispatch_to_extension_op (op , self , other )
833
- return self ._constructor (res_values , index = self .index , name = res_name )
834
850
835
851
elif is_datetime64_dtype (self ) or is_datetime64tz_dtype (self ):
836
852
# Dispatch to DatetimeIndex to ensure identical
837
853
# Series/Index behavior
838
854
from pandas .core .arrays import DatetimeArray
839
855
840
856
res_values = dispatch_to_extension_op (op , DatetimeArray (self ), other )
841
- return self ._constructor (res_values , index = self .index , name = res_name )
842
857
843
858
elif is_timedelta64_dtype (self ):
844
859
from pandas .core .arrays import TimedeltaArray
845
860
846
861
res_values = dispatch_to_extension_op (op , TimedeltaArray (self ), other )
847
- return self ._constructor (res_values , index = self .index , name = res_name )
848
862
849
863
elif is_extension_array_dtype (self ) or (
850
864
is_extension_array_dtype (other ) and not is_scalar (other )
851
865
):
852
866
# Note: the `not is_scalar(other)` condition rules out
853
- # e.g. other == "category"
867
+ # e.g. other == "category"
854
868
res_values = dispatch_to_extension_op (op , self , other )
855
- return self ._constructor (res_values , index = self .index ).rename (res_name )
856
-
857
- elif isinstance (other , ABCSeries ):
858
- # By this point we have checked that self._indexed_same(other)
859
- res_values = na_op (self .values , other .values )
860
- # rename is needed in case res_name is None and res_values.name
861
- # is not.
862
- return self ._constructor (
863
- res_values , index = self .index , name = res_name
864
- ).rename (res_name )
865
-
866
- elif isinstance (other , (np .ndarray , ABCIndexClass )):
867
- # do not check length of zerodim array
868
- # as it will broadcast
869
- if other .ndim != 0 and len (self ) != len (other ):
870
- raise ValueError ("Lengths must match to compare" )
871
-
872
- res_values = na_op (self .values , np .asarray (other ))
873
- result = self ._constructor (res_values , index = self .index )
874
- # rename is needed in case res_name is None and self.name
875
- # is not.
876
- return result .__finalize__ (self ).rename (res_name )
877
869
878
870
elif is_scalar (other ) and isna (other ):
879
871
# numpy does not like comparisons vs None
880
872
if op is operator .ne :
881
873
res_values = np .ones (len (self ), dtype = bool )
882
874
else :
883
875
res_values = np .zeros (len (self ), dtype = bool )
884
- return self ._constructor (
885
- res_values , index = self .index , name = res_name , dtype = "bool"
886
- )
887
876
888
877
else :
889
- values = self .to_numpy ()
878
+ lvalues = extract_array (self , extract_numpy = True )
879
+ rvalues = extract_array (other , extract_numpy = True )
890
880
891
881
with np .errstate (all = "ignore" ):
892
- res = na_op (values , other )
893
- if is_scalar (res ):
882
+ res_values = na_op (lvalues , rvalues )
883
+ if is_scalar (res_values ):
894
884
raise TypeError (
895
885
"Could not compare {typ} type with Series" .format (typ = type (other ))
896
886
)
897
887
898
- # always return a full value series here
899
- res_values = extract_array (res , extract_numpy = True )
900
- return self ._constructor (
901
- res_values , index = self .index , name = res_name , dtype = "bool"
902
- )
888
+ result = self ._constructor (res_values , index = self .index )
889
+ # rename is needed in case res_name is None and result.name
890
+ # is not.
891
+ return finalizer (result ).rename (res_name )
903
892
904
893
wrapper .__name__ = op_name
905
894
return wrapper
0 commit comments