5454)
5555
5656if TYPE_CHECKING :
57- from pandas import DataFrame # noqa:F401
57+ from pandas import DataFrame , Series # noqa:F401
5858
5959# -----------------------------------------------------------------------------
6060# constants
@@ -459,19 +459,7 @@ def _combine_series_frame(left, right, func, axis: int):
459459 # We assume that self.align(other, ...) has already been called
460460
461461 rvalues = right ._values
462- if isinstance (rvalues , np .ndarray ):
463- # TODO(EA2D): no need to special-case with 2D EAs
464- # We can operate block-wise
465- if axis == 0 :
466- rvalues = rvalues .reshape (- 1 , 1 )
467- else :
468- rvalues = rvalues .reshape (1 , - 1 )
469-
470- rvalues = np .broadcast_to (rvalues , left .shape )
471-
472- array_op = get_array_op (func )
473- bm = left ._mgr .apply (array_op , right = rvalues .T , align_keys = ["right" ])
474- return type (left )(bm )
462+ assert not isinstance (rvalues , np .ndarray ) # handled by align_series_as_frame
475463
476464 if axis == 0 :
477465 new_data = dispatch_to_series (left , right , func )
@@ -567,6 +555,7 @@ def to_series(right):
567555 left , right = left .align (
568556 right , join = "outer" , axis = axis , level = level , copy = False
569557 )
558+ right = _maybe_align_series_as_frame (left , right , axis )
570559
571560 return left , right
572561
@@ -627,6 +616,25 @@ def _frame_arith_method_with_reindex(
627616 return result .reindex (join_columns , axis = 1 )
628617
629618
619+ def _maybe_align_series_as_frame (frame : "DataFrame" , series : "Series" , axis : int ):
620+ """
621+ If the Series operand is not EA-dtype, we can broadcast to 2D and operate
622+ blockwise.
623+ """
624+ rvalues = series ._values
625+ if not isinstance (rvalues , np .ndarray ):
626+ # TODO(EA2D): no need to special-case with 2D EAs
627+ return series
628+
629+ if axis == 0 :
630+ rvalues = rvalues .reshape (- 1 , 1 )
631+ else :
632+ rvalues = rvalues .reshape (1 , - 1 )
633+
634+ rvalues = np .broadcast_to (rvalues , frame .shape )
635+ return type (frame )(rvalues , index = frame .index , columns = frame .columns )
636+
637+
630638def _arith_method_FRAME (cls : Type ["DataFrame" ], op , special : bool ):
631639 # This is the only function where `special` can be either True or False
632640 op_name = _get_op_name (op , special )
@@ -648,6 +656,11 @@ def f(self, other, axis=default_axis, level=None, fill_value=None):
648656 ):
649657 return _frame_arith_method_with_reindex (self , other , op )
650658
659+ if isinstance (other , ABCSeries ) and fill_value is not None :
660+ # TODO: We could allow this in cases where we end up going
661+ # through the DataFrame path
662+ raise NotImplementedError (f"fill_value { fill_value } not supported." )
663+
651664 # TODO: why are we passing flex=True instead of flex=not special?
652665 # 15 tests fail if we pass flex=not special instead
653666 self , other = _align_method_FRAME (self , other , axis , flex = True , level = level )
@@ -657,9 +670,6 @@ def f(self, other, axis=default_axis, level=None, fill_value=None):
657670 new_data = self ._combine_frame (other , na_op , fill_value )
658671
659672 elif isinstance (other , ABCSeries ):
660- if fill_value is not None :
661- raise NotImplementedError (f"fill_value { fill_value } not supported." )
662-
663673 axis = self ._get_axis_number (axis ) if axis is not None else 1
664674 new_data = _combine_series_frame (self , other , op , axis = axis )
665675 else :
0 commit comments