@@ -943,6 +943,134 @@ def should_series_dispatch(left, right, op):
943
943
return False
944
944
945
945
946
+ def dispatch_to_series (left , right , func , str_rep = None , axis = None ):
947
+ """
948
+ Evaluate the frame operation func(left, right) by evaluating
949
+ column-by-column, dispatching to the Series implementation.
950
+
951
+ Parameters
952
+ ----------
953
+ left : DataFrame
954
+ right : scalar or DataFrame
955
+ func : arithmetic or comparison operator
956
+ str_rep : str or None, default None
957
+ axis : {None, 0, 1, "index", "columns"}
958
+
959
+ Returns
960
+ -------
961
+ DataFrame
962
+ """
963
+ # Note: we use iloc to access columns for compat with cases
964
+ # with non-unique columns.
965
+ import pandas .core .computation .expressions as expressions
966
+
967
+ right = lib .item_from_zerodim (right )
968
+ if lib .is_scalar (right ):
969
+
970
+ def column_op (a , b ):
971
+ return {i : func (a .iloc [:, i ], b )
972
+ for i in range (len (a .columns ))}
973
+
974
+ elif isinstance (right , ABCDataFrame ):
975
+ assert right ._indexed_same (left )
976
+
977
+ def column_op (a , b ):
978
+ return {i : func (a .iloc [:, i ], b .iloc [:, i ])
979
+ for i in range (len (a .columns ))}
980
+
981
+ elif isinstance (right , ABCSeries ) and axis == "columns" :
982
+ # We only get here if called via left._combine_match_columns,
983
+ # in which case we specifically want to operate row-by-row
984
+ assert right .index .equals (left .columns )
985
+
986
+ def column_op (a , b ):
987
+ return {i : func (a .iloc [:, i ], b .iloc [i ])
988
+ for i in range (len (a .columns ))}
989
+
990
+ elif isinstance (right , ABCSeries ):
991
+ assert right .index .equals (left .index ) # Handle other cases later
992
+
993
+ def column_op (a , b ):
994
+ return {i : func (a .iloc [:, i ], b )
995
+ for i in range (len (a .columns ))}
996
+
997
+ else :
998
+ # Remaining cases have less-obvious dispatch rules
999
+ raise NotImplementedError (right )
1000
+
1001
+ new_data = expressions .evaluate (column_op , str_rep , left , right )
1002
+
1003
+ result = left ._constructor (new_data , index = left .index , copy = False )
1004
+ # Pin columns instead of passing to constructor for compat with
1005
+ # non-unique columns case
1006
+ result .columns = left .columns
1007
+ return result
1008
+
1009
+
1010
+ def dispatch_to_index_op (op , left , right , index_class ):
1011
+ """
1012
+ Wrap Series left in the given index_class to delegate the operation op
1013
+ to the index implementation. DatetimeIndex and TimedeltaIndex perform
1014
+ type checking, timezone handling, overflow checks, etc.
1015
+
1016
+ Parameters
1017
+ ----------
1018
+ op : binary operator (operator.add, operator.sub, ...)
1019
+ left : Series
1020
+ right : object
1021
+ index_class : DatetimeIndex or TimedeltaIndex
1022
+
1023
+ Returns
1024
+ -------
1025
+ result : object, usually DatetimeIndex, TimedeltaIndex, or Series
1026
+ """
1027
+ left_idx = index_class (left )
1028
+
1029
+ # avoid accidentally allowing integer add/sub. For datetime64[tz] dtypes,
1030
+ # left_idx may inherit a freq from a cached DatetimeIndex.
1031
+ # See discussion in GH#19147.
1032
+ if getattr (left_idx , 'freq' , None ) is not None :
1033
+ left_idx = left_idx ._shallow_copy (freq = None )
1034
+ try :
1035
+ result = op (left_idx , right )
1036
+ except NullFrequencyError :
1037
+ # DatetimeIndex and TimedeltaIndex with freq == None raise ValueError
1038
+ # on add/sub of integers (or int-like). We re-raise as a TypeError.
1039
+ raise TypeError ('incompatible type for a datetime/timedelta '
1040
+ 'operation [{name}]' .format (name = op .__name__ ))
1041
+ return result
1042
+
1043
+
1044
+ def dispatch_to_extension_op (op , left , right ):
1045
+ """
1046
+ Assume that left or right is a Series backed by an ExtensionArray,
1047
+ apply the operator defined by op.
1048
+ """
1049
+
1050
+ # The op calls will raise TypeError if the op is not defined
1051
+ # on the ExtensionArray
1052
+
1053
+ # unbox Series and Index to arrays
1054
+ if isinstance (left , (ABCSeries , ABCIndexClass )):
1055
+ new_left = left ._values
1056
+ else :
1057
+ new_left = left
1058
+
1059
+ if isinstance (right , (ABCSeries , ABCIndexClass )):
1060
+ new_right = right ._values
1061
+ else :
1062
+ new_right = right
1063
+
1064
+ res_values = op (new_left , new_right )
1065
+ res_name = get_op_result_name (left , right )
1066
+
1067
+ if op .__name__ in ['divmod' , 'rdivmod' ]:
1068
+ return _construct_divmod_result (
1069
+ left , res_values , left .index , res_name )
1070
+
1071
+ return _construct_result (left , res_values , left .index , res_name )
1072
+
1073
+
946
1074
# -----------------------------------------------------------------------------
947
1075
# Functions that add arithmetic methods to objects, given arithmetic factory
948
1076
# methods
@@ -1202,36 +1330,6 @@ def _construct_divmod_result(left, result, index, name, dtype=None):
1202
1330
)
1203
1331
1204
1332
1205
- def dispatch_to_extension_op (op , left , right ):
1206
- """
1207
- Assume that left or right is a Series backed by an ExtensionArray,
1208
- apply the operator defined by op.
1209
- """
1210
-
1211
- # The op calls will raise TypeError if the op is not defined
1212
- # on the ExtensionArray
1213
-
1214
- # unbox Series and Index to arrays
1215
- if isinstance (left , (ABCSeries , ABCIndexClass )):
1216
- new_left = left ._values
1217
- else :
1218
- new_left = left
1219
-
1220
- if isinstance (right , (ABCSeries , ABCIndexClass )):
1221
- new_right = right ._values
1222
- else :
1223
- new_right = right
1224
-
1225
- res_values = op (new_left , new_right )
1226
- res_name = get_op_result_name (left , right )
1227
-
1228
- if op .__name__ in ['divmod' , 'rdivmod' ]:
1229
- return _construct_divmod_result (
1230
- left , res_values , left .index , res_name )
1231
-
1232
- return _construct_result (left , res_values , left .index , res_name )
1233
-
1234
-
1235
1333
def _arith_method_SERIES (cls , op , special ):
1236
1334
"""
1237
1335
Wrapper function for Series arithmetic operations, to avoid
@@ -1329,40 +1427,6 @@ def wrapper(left, right):
1329
1427
return wrapper
1330
1428
1331
1429
1332
- def dispatch_to_index_op (op , left , right , index_class ):
1333
- """
1334
- Wrap Series left in the given index_class to delegate the operation op
1335
- to the index implementation. DatetimeIndex and TimedeltaIndex perform
1336
- type checking, timezone handling, overflow checks, etc.
1337
-
1338
- Parameters
1339
- ----------
1340
- op : binary operator (operator.add, operator.sub, ...)
1341
- left : Series
1342
- right : object
1343
- index_class : DatetimeIndex or TimedeltaIndex
1344
-
1345
- Returns
1346
- -------
1347
- result : object, usually DatetimeIndex, TimedeltaIndex, or Series
1348
- """
1349
- left_idx = index_class (left )
1350
-
1351
- # avoid accidentally allowing integer add/sub. For datetime64[tz] dtypes,
1352
- # left_idx may inherit a freq from a cached DatetimeIndex.
1353
- # See discussion in GH#19147.
1354
- if getattr (left_idx , 'freq' , None ) is not None :
1355
- left_idx = left_idx ._shallow_copy (freq = None )
1356
- try :
1357
- result = op (left_idx , right )
1358
- except NullFrequencyError :
1359
- # DatetimeIndex and TimedeltaIndex with freq == None raise ValueError
1360
- # on add/sub of integers (or int-like). We re-raise as a TypeError.
1361
- raise TypeError ('incompatible type for a datetime/timedelta '
1362
- 'operation [{name}]' .format (name = op .__name__ ))
1363
- return result
1364
-
1365
-
1366
1430
def _comp_method_OBJECT_ARRAY (op , x , y ):
1367
1431
if isinstance (y , list ):
1368
1432
y = construct_1d_object_array_from_listlike (y )
@@ -1661,69 +1725,6 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
1661
1725
# -----------------------------------------------------------------------------
1662
1726
# DataFrame
1663
1727
1664
- def dispatch_to_series (left , right , func , str_rep = None , axis = None ):
1665
- """
1666
- Evaluate the frame operation func(left, right) by evaluating
1667
- column-by-column, dispatching to the Series implementation.
1668
-
1669
- Parameters
1670
- ----------
1671
- left : DataFrame
1672
- right : scalar or DataFrame
1673
- func : arithmetic or comparison operator
1674
- str_rep : str or None, default None
1675
- axis : {None, 0, 1, "index", "columns"}
1676
-
1677
- Returns
1678
- -------
1679
- DataFrame
1680
- """
1681
- # Note: we use iloc to access columns for compat with cases
1682
- # with non-unique columns.
1683
- import pandas .core .computation .expressions as expressions
1684
-
1685
- right = lib .item_from_zerodim (right )
1686
- if lib .is_scalar (right ):
1687
-
1688
- def column_op (a , b ):
1689
- return {i : func (a .iloc [:, i ], b )
1690
- for i in range (len (a .columns ))}
1691
-
1692
- elif isinstance (right , ABCDataFrame ):
1693
- assert right ._indexed_same (left )
1694
-
1695
- def column_op (a , b ):
1696
- return {i : func (a .iloc [:, i ], b .iloc [:, i ])
1697
- for i in range (len (a .columns ))}
1698
-
1699
- elif isinstance (right , ABCSeries ) and axis == "columns" :
1700
- # We only get here if called via left._combine_match_columns,
1701
- # in which case we specifically want to operate row-by-row
1702
- assert right .index .equals (left .columns )
1703
-
1704
- def column_op (a , b ):
1705
- return {i : func (a .iloc [:, i ], b .iloc [i ])
1706
- for i in range (len (a .columns ))}
1707
-
1708
- elif isinstance (right , ABCSeries ):
1709
- assert right .index .equals (left .index ) # Handle other cases later
1710
-
1711
- def column_op (a , b ):
1712
- return {i : func (a .iloc [:, i ], b )
1713
- for i in range (len (a .columns ))}
1714
-
1715
- else :
1716
- # Remaining cases have less-obvious dispatch rules
1717
- raise NotImplementedError (right )
1718
-
1719
- new_data = expressions .evaluate (column_op , str_rep , left , right )
1720
-
1721
- result = left ._constructor (new_data , index = left .index , copy = False )
1722
- # Pin columns instead of passing to constructor for compat with
1723
- # non-unique columns case
1724
- result .columns = left .columns
1725
- return result
1726
-
1727
1728
1728
1729
def _combine_series_frame (self , other , func , fill_value = None , axis = None ,
1729
1730
level = None ):
0 commit comments