27
27
is_integer_dtype , is_categorical_dtype ,
28
28
is_object_dtype , is_timedelta64_dtype ,
29
29
is_datetime64_dtype , is_datetime64tz_dtype ,
30
- is_bool_dtype ,
30
+ is_bool_dtype , is_extension_array_dtype ,
31
31
is_list_like ,
32
32
is_scalar ,
33
33
_ensure_object )
@@ -1003,8 +1003,18 @@ def _arith_method_SERIES(cls, op, special):
1003
1003
if op is divmod else _construct_result )
1004
1004
1005
1005
def na_op (x , y ):
1006
- import pandas .core .computation .expressions as expressions
1006
+ # handle extension array ops
1007
+ # TODO(extension)
1008
+ # the ops *between* non-same-type extension arrays are not
1009
+ # very well defined
1010
+ if (is_extension_array_dtype (x ) or is_extension_array_dtype (y )):
1011
+ if (op_name .startswith ('__r' ) and not
1012
+ is_extension_array_dtype (y ) and not
1013
+ is_scalar (y )):
1014
+ y = x .__class__ ._from_sequence (y )
1015
+ return op (x , y )
1007
1016
1017
+ import pandas .core .computation .expressions as expressions
1008
1018
try :
1009
1019
result = expressions .evaluate (op , str_rep , x , y , ** eval_kwargs )
1010
1020
except TypeError :
@@ -1025,6 +1035,7 @@ def na_op(x, y):
1025
1035
return result
1026
1036
1027
1037
def safe_na_op (lvalues , rvalues ):
1038
+ # all others
1028
1039
try :
1029
1040
with np .errstate (all = 'ignore' ):
1030
1041
return na_op (lvalues , rvalues )
@@ -1035,14 +1046,21 @@ def safe_na_op(lvalues, rvalues):
1035
1046
raise
1036
1047
1037
1048
def wrapper (left , right ):
1038
-
1039
1049
if isinstance (right , ABCDataFrame ):
1040
1050
return NotImplemented
1041
1051
1042
1052
left , right = _align_method_SERIES (left , right )
1043
1053
res_name = get_op_result_name (left , right )
1044
1054
1045
- if is_datetime64_dtype (left ) or is_datetime64tz_dtype (left ):
1055
+ if is_categorical_dtype (left ):
1056
+ raise TypeError ("{typ} cannot perform the operation "
1057
+ "{op}" .format (typ = type (left ).__name__ , op = str_rep ))
1058
+
1059
+ elif (is_extension_array_dtype (left ) or
1060
+ is_extension_array_dtype (right )):
1061
+ pass
1062
+
1063
+ elif is_datetime64_dtype (left ) or is_datetime64tz_dtype (left ):
1046
1064
result = dispatch_to_index_op (op , left , right , pd .DatetimeIndex )
1047
1065
return construct_result (left , result ,
1048
1066
index = left .index , name = res_name ,
@@ -1054,10 +1072,6 @@ def wrapper(left, right):
1054
1072
index = left .index , name = res_name ,
1055
1073
dtype = result .dtype )
1056
1074
1057
- elif is_categorical_dtype (left ):
1058
- raise TypeError ("{typ} cannot perform the operation "
1059
- "{op}" .format (typ = type (left ).__name__ , op = str_rep ))
1060
-
1061
1075
lvalues = left .values
1062
1076
rvalues = right
1063
1077
if isinstance (rvalues , ABCSeries ):
@@ -1136,6 +1150,14 @@ def na_op(x, y):
1136
1150
# The `not is_scalar(y)` check excludes the string "category"
1137
1151
return op (y , x )
1138
1152
1153
+ # handle extension array ops
1154
+ # TODO(extension)
1155
+ # the ops *between* non-same-type extension arrays are not
1156
+ # very well defined
1157
+ elif (is_extension_array_dtype (x ) or
1158
+ is_extension_array_dtype (y )):
1159
+ return op (x , y )
1160
+
1139
1161
elif is_object_dtype (x .dtype ):
1140
1162
result = _comp_method_OBJECT_ARRAY (op , x , y )
1141
1163
0 commit comments