@@ -1621,7 +1621,7 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
1621
1621
# -----------------------------------------------------------------------------
1622
1622
# DataFrame
1623
1623
1624
- def dispatch_to_series (left , right , func ):
1624
+ def dispatch_to_series (left , right , func , str_rep = None ):
1625
1625
"""
1626
1626
Evaluate the frame operation func(left, right) by evaluating
1627
1627
column-by-column, dispatching to the Series implementation.
@@ -1631,24 +1631,42 @@ def dispatch_to_series(left, right, func):
1631
1631
left : DataFrame
1632
1632
right : scalar or DataFrame
1633
1633
func : arithmetic or comparison operator
1634
+ str_rep : str or None, default None
1634
1635
1635
1636
Returns
1636
1637
-------
1637
1638
DataFrame
1638
1639
"""
1639
1640
# Note: we use iloc to access columns for compat with cases
1640
1641
# with non-unique columns.
1642
+ import pandas .core .computation .expressions as expressions
1643
+
1641
1644
right = lib .item_from_zerodim (right )
1642
1645
if lib .is_scalar (right ):
1643
- new_data = {i : func (left .iloc [:, i ], right )
1644
- for i in range (len (left .columns ))}
1646
+
1647
+ def column_op (a , b ):
1648
+ return {i : func (a .iloc [:, i ], b )
1649
+ for i in range (len (a .columns ))}
1650
+
1645
1651
elif isinstance (right , ABCDataFrame ):
1646
1652
assert right ._indexed_same (left )
1647
- new_data = {i : func (left .iloc [:, i ], right .iloc [:, i ])
1648
- for i in range (len (left .columns ))}
1653
+
1654
+ def column_op (a , b ):
1655
+ return {i : func (a .iloc [:, i ], b .iloc [:, i ])
1656
+ for i in range (len (a .columns ))}
1657
+
1658
+ elif isinstance (right , ABCSeries ):
1659
+ assert right .index .equals (left .index ) # Handle other cases later
1660
+
1661
+ def column_op (a , b ):
1662
+ return {i : func (a .iloc [:, i ], b )
1663
+ for i in range (len (a .columns ))}
1664
+
1649
1665
else :
1650
1666
# Remaining cases have less-obvious dispatch rules
1651
- raise NotImplementedError
1667
+ raise NotImplementedError (right )
1668
+
1669
+ new_data = expressions .evaluate (column_op , str_rep , left , right )
1652
1670
1653
1671
result = left ._constructor (new_data , index = left .index , copy = False )
1654
1672
# Pin columns instead of passing to constructor for compat with
@@ -1818,7 +1836,7 @@ def f(self, other, axis=default_axis, level=None):
1818
1836
if not self ._indexed_same (other ):
1819
1837
self , other = self .align (other , 'outer' ,
1820
1838
level = level , copy = False )
1821
- return self . _compare_frame ( other , na_op , str_rep )
1839
+ return dispatch_to_series ( self , other , na_op , str_rep )
1822
1840
1823
1841
elif isinstance (other , ABCSeries ):
1824
1842
return _combine_series_frame (self , other , na_op ,
@@ -1843,7 +1861,7 @@ def f(self, other):
1843
1861
if not self ._indexed_same (other ):
1844
1862
raise ValueError ('Can only compare identically-labeled '
1845
1863
'DataFrame objects' )
1846
- return self . _compare_frame ( other , func , str_rep )
1864
+ return dispatch_to_series ( self , other , func , str_rep )
1847
1865
1848
1866
elif isinstance (other , ABCSeries ):
1849
1867
return _combine_series_frame (self , other , func ,
0 commit comments