diff --git a/doc/source/whatsnew/v1.5.2.rst b/doc/source/whatsnew/v1.5.2.rst index dd909415d9e851..c1fde3d13ef744 100644 --- a/doc/source/whatsnew/v1.5.2.rst +++ b/doc/source/whatsnew/v1.5.2.rst @@ -15,6 +15,7 @@ Fixed regressions ~~~~~~~~~~~~~~~~~ - Fixed regression in :meth:`MultiIndex.join` for extension array dtypes (:issue:`49277`) - Fixed regression in :meth:`Series.replace` raising ``RecursionError`` with numeric dtype and when specifying ``value=None`` (:issue:`45725`) +- Fixed regression in arithmetic operations for :class:`DataFrame` with :class:`MultiIndex` columns with different dtypes (:issue:`49769`) - Fixed regression in :meth:`DataFrame.plot` preventing :class:`~matplotlib.colors.Colormap` instance from being passed using the ``colormap`` argument if Matplotlib 3.6+ is used (:issue:`49374`) - Fixed regression in :func:`date_range` returning an invalid set of periods for ``CustomBusinessDay`` frequency and ``start`` date with timezone (:issue:`49441`) diff --git a/pandas/core/ops/__init__.py b/pandas/core/ops/__init__.py index 4007d3cfa46da8..af27ff67599ac6 100644 --- a/pandas/core/ops/__init__.py +++ b/pandas/core/ops/__init__.py @@ -338,7 +338,9 @@ def should_reindex_frame_op( left_uniques = left.columns.unique() right_uniques = right.columns.unique() cols = left_uniques.intersection(right_uniques) - if len(cols) and not (cols.equals(left_uniques) and cols.equals(right_uniques)): + if len(cols) and not ( + len(cols) == len(left_uniques) and len(cols) == len(right_uniques) + ): # TODO: is there a shortcut available when len(cols) == 0? return True diff --git a/pandas/tests/frame/test_arithmetic.py b/pandas/tests/frame/test_arithmetic.py index 822e761f63ae89..545482e6d3dada 100644 --- a/pandas/tests/frame/test_arithmetic.py +++ b/pandas/tests/frame/test_arithmetic.py @@ -1133,6 +1133,26 @@ def test_binop_other(self, op, value, dtype, switch_numexpr_min_elements): expected = op(df, value).dtypes tm.assert_series_equal(result, expected) + def test_arithmetic_midx_cols_different_dtypes(self): + # GH#49769 + midx = MultiIndex.from_arrays([Series([1, 2]), Series([3, 4])]) + midx2 = MultiIndex.from_arrays([Series([1, 2], dtype="Int8"), Series([3, 4])]) + left = DataFrame([[1, 2], [3, 4]], columns=midx) + right = DataFrame([[1, 2], [3, 4]], columns=midx2) + result = left - right + expected = DataFrame([[0, 0], [0, 0]], columns=midx) + tm.assert_frame_equal(result, expected) + + def test_arithmetic_midx_cols_different_dtypes_different_order(self): + # GH#49769 + midx = MultiIndex.from_arrays([Series([1, 2]), Series([3, 4])]) + midx2 = MultiIndex.from_arrays([Series([2, 1], dtype="Int8"), Series([4, 3])]) + left = DataFrame([[1, 2], [3, 4]], columns=midx) + right = DataFrame([[1, 2], [3, 4]], columns=midx2) + result = left - right + expected = DataFrame([[-1, 1], [-1, 1]], columns=midx) + tm.assert_frame_equal(result, expected) + def test_frame_with_zero_len_series_corner_cases(): # GH#28600