@@ -741,6 +741,7 @@ def na_op(x, y):
741
741
if is_categorical_dtype (x ):
742
742
return op (x , y )
743
743
elif is_categorical_dtype (y ) and not is_scalar (y ):
744
+ # the `not is_scalar(y)` check avoids catching string "category"
744
745
return op (y , x )
745
746
746
747
elif is_object_dtype (x .dtype ):
@@ -750,7 +751,6 @@ def na_op(x, y):
750
751
raise TypeError ("invalid type comparison" )
751
752
752
753
else :
753
-
754
754
# we want to compare like types
755
755
# we only want to convert to integer like if
756
756
# we are not NotImplemented, otherwise
@@ -759,23 +759,18 @@ def na_op(x, y):
759
759
760
760
# we have a datetime/timedelta and may need to convert
761
761
mask = None
762
- if (needs_i8_conversion (x ) or
763
- (not is_scalar (y ) and needs_i8_conversion (y ))):
764
-
765
- if is_scalar (y ):
766
- mask = isna (x )
767
- y = libindex .convert_scalar (x , com ._values_from_object (y ))
768
- else :
769
- mask = isna (x ) | isna (y )
770
- y = y .view ('i8' )
762
+ if not is_scalar (y ) and needs_i8_conversion (y ):
763
+ mask = isna (x ) | isna (y )
764
+ y = y .view ('i8' )
771
765
x = x .view ('i8' )
772
766
773
- try :
767
+ method = getattr (x , name , None )
768
+ if method is not None :
774
769
with np .errstate (all = 'ignore' ):
775
770
result = getattr (x , name )(y )
776
771
if result is NotImplemented :
777
772
raise TypeError ("invalid type comparison" )
778
- except AttributeError :
773
+ else :
779
774
result = op (x , y )
780
775
781
776
if mask is not None and mask .any ():
@@ -788,17 +783,36 @@ def wrapper(self, other, axis=None):
788
783
if axis is not None :
789
784
self ._get_axis_number (axis )
790
785
786
+ res_name = _get_series_op_result_name (self , other )
787
+
791
788
if isinstance (other , ABCDataFrame ): # pragma: no cover
792
789
# Defer to DataFrame implementation; fail early
793
790
return NotImplemented
794
791
792
+ elif isinstance (other , ABCSeries ) and not self ._indexed_same (other ):
793
+ raise ValueError ('Can only compare identically-labeled Series '
794
+ 'objects' )
795
+
796
+ elif is_datetime64_dtype (self ) or is_datetime64tz_dtype (self ):
797
+ res_values = dispatch_to_index_op (op , self , other ,
798
+ pd .DatetimeIndex )
799
+ return _construct_result (self , res_values ,
800
+ index = self .index , name = res_name ,
801
+ dtype = res_values .dtype )
802
+
803
+ elif is_timedelta64_dtype (self ):
804
+ res_values = dispatch_to_index_op (op , self , other ,
805
+ pd .TimedeltaIndex )
806
+ return _construct_result (self , res_values ,
807
+ index = self .index , name = res_name ,
808
+ dtype = res_values .dtype )
809
+
795
810
elif isinstance (other , ABCSeries ):
811
+ # By this point we know that self._indexed_same(other)
796
812
name = com ._maybe_match_name (self , other )
797
- if not self ._indexed_same (other ):
798
- msg = 'Can only compare identically-labeled Series objects'
799
- raise ValueError (msg )
800
813
res_values = na_op (self .values , other .values )
801
- return self ._constructor (res_values , index = self .index , name = name )
814
+ return self ._constructor (res_values , index = self .index ,
815
+ name = res_name )
802
816
803
817
elif isinstance (other , (np .ndarray , pd .Index )):
804
818
# do not check length of zerodim array
@@ -836,7 +850,7 @@ def wrapper(self, other, axis=None):
836
850
res = op (self .values , other )
837
851
else :
838
852
values = self .get_values ()
839
- if isinstance (other , ( list , np . ndarray ) ):
853
+ if isinstance (other , list ):
840
854
other = np .asarray (other )
841
855
842
856
with np .errstate (all = 'ignore' ):
0 commit comments