@@ -943,6 +943,134 @@ def should_series_dispatch(left, right, op):
943943 return False
944944
945945
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+
9461074# -----------------------------------------------------------------------------
9471075# Functions that add arithmetic methods to objects, given arithmetic factory
9481076# methods
@@ -1202,36 +1330,6 @@ def _construct_divmod_result(left, result, index, name, dtype=None):
12021330 )
12031331
12041332
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-
12351333def _arith_method_SERIES (cls , op , special ):
12361334 """
12371335 Wrapper function for Series arithmetic operations, to avoid
@@ -1329,40 +1427,6 @@ def wrapper(left, right):
13291427 return wrapper
13301428
13311429
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-
13661430def _comp_method_OBJECT_ARRAY (op , x , y ):
13671431 if isinstance (y , list ):
13681432 y = construct_1d_object_array_from_listlike (y )
@@ -1661,69 +1725,6 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
16611725# -----------------------------------------------------------------------------
16621726# DataFrame
16631727
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-
17271728
17281729def _combine_series_frame (self , other , func , fill_value = None , axis = None ,
17291730 level = None ):
0 commit comments