5
5
"""
6
6
import datetime
7
7
import operator
8
- from typing import Set , Tuple , Union
8
+ from typing import TYPE_CHECKING , Set , Tuple , Union
9
9
10
10
import numpy as np
11
11
60
60
rxor ,
61
61
)
62
62
63
+ if TYPE_CHECKING :
64
+ from pandas import DataFrame # noqa:F401
65
+
63
66
# -----------------------------------------------------------------------------
64
67
# constants
65
68
ARITHMETIC_BINOPS : Set [str ] = {
@@ -675,6 +678,58 @@ def to_series(right):
675
678
return right
676
679
677
680
681
+ def _should_reindex_frame_op (
682
+ left : "DataFrame" , right , axis , default_axis : int , fill_value , level
683
+ ) -> bool :
684
+ """
685
+ Check if this is an operation between DataFrames that will need to reindex.
686
+ """
687
+ assert isinstance (left , ABCDataFrame )
688
+
689
+ if not isinstance (right , ABCDataFrame ):
690
+ return False
691
+
692
+ if fill_value is None and level is None and axis is default_axis :
693
+ # TODO: any other cases we should handle here?
694
+ cols = left .columns .intersection (right .columns )
695
+ if not (cols .equals (left .columns ) and cols .equals (right .columns )):
696
+ return True
697
+
698
+ return False
699
+
700
+
701
+ def _frame_arith_method_with_reindex (
702
+ left : "DataFrame" , right : "DataFrame" , op
703
+ ) -> "DataFrame" :
704
+ """
705
+ For DataFrame-with-DataFrame operations that require reindexing,
706
+ operate only on shared columns, then reindex.
707
+
708
+ Parameters
709
+ ----------
710
+ left : DataFrame
711
+ right : DataFrame
712
+ op : binary operator
713
+
714
+ Returns
715
+ -------
716
+ DataFrame
717
+ """
718
+ # GH#31623, only operate on shared columns
719
+ cols = left .columns .intersection (right .columns )
720
+
721
+ new_left = left [cols ]
722
+ new_right = right [cols ]
723
+ result = op (new_left , new_right )
724
+
725
+ # Do the join on the columns instead of using _align_method_FRAME
726
+ # to avoid constructing two potentially large/sparse DataFrames
727
+ join_columns , _ , _ = left .columns .join (
728
+ right .columns , how = "outer" , level = None , return_indexers = True
729
+ )
730
+ return result .reindex (join_columns , axis = 1 )
731
+
732
+
678
733
def _arith_method_FRAME (cls , op , special ):
679
734
str_rep = _get_opstr (op )
680
735
op_name = _get_op_name (op , special )
@@ -692,6 +747,9 @@ def _arith_method_FRAME(cls, op, special):
692
747
@Appender (doc )
693
748
def f (self , other , axis = default_axis , level = None , fill_value = None ):
694
749
750
+ if _should_reindex_frame_op (self , other , axis , default_axis , fill_value , level ):
751
+ return _frame_arith_method_with_reindex (self , other , op )
752
+
695
753
other = _align_method_FRAME (self , other , axis )
696
754
697
755
if isinstance (other , ABCDataFrame ):
0 commit comments