From 073013fa4e94d7f69b281e17f3442731e4236d97 Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 23 Jan 2022 04:05:43 +0100 Subject: [PATCH] BUG: align not adding levels only on one side if intersection is equal --- doc/source/whatsnew/v1.5.0.rst | 1 + pandas/core/series.py | 4 ++- pandas/tests/series/methods/test_align.py | 38 +++++++++++++++++++++++ pandas/tests/series/test_arithmetic.py | 4 +-- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 1ae76984484af..042a73d42a447 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -210,6 +210,7 @@ Indexing ^^^^^^^^ - Bug in :meth:`loc.__getitem__` with a list of keys causing an internal inconsistency that could lead to a disconnect between ``frame.at[x, y]`` vs ``frame[y].loc[x]`` (:issue:`22372`) - Bug in :meth:`DataFrame.iloc` where indexing a single row on a :class:`DataFrame` with a single ExtensionDtype column gave a copy instead of a view on the underlying data (:issue:`45241`) +- Bug in :meth:`Series.align` does not create :class:`MultiIndex` with union of levels when both MultiIndexes intersections are identical (:issue:`45224`) - Bug in :meth:`Series.__setitem__` with a non-integer :class:`Index` when using an integer key to set a value that cannot be set inplace where a ``ValueError`` was raised insead of casting to a common dtype (:issue:`45070`) - Bug when setting a value too large for a :class:`Series` dtype failing to coerce to a common type (:issue:`26049`, :issue:`32878`) - diff --git a/pandas/core/series.py b/pandas/core/series.py index 4e69596539bed..2334cb838094f 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -4467,7 +4467,9 @@ def _reindex_indexer( ) -> Series: # Note: new_index is None iff indexer is None # if not None, indexer is np.intp - if indexer is None: + if indexer is None and ( + new_index is None or new_index.names == self.index.names + ): if copy: return self.copy() return self diff --git a/pandas/tests/series/methods/test_align.py b/pandas/tests/series/methods/test_align.py index 8769ab048a136..33e2b1ccecf2d 100644 --- a/pandas/tests/series/methods/test_align.py +++ b/pandas/tests/series/methods/test_align.py @@ -184,3 +184,41 @@ def test_align_periodindex(join_type): # TODO: assert something? ts.align(ts[::2], join=join_type) + + +def test_align_left_fewer_levels(): + # GH#45224 + left = Series([2], index=pd.MultiIndex.from_tuples([(1, 3)], names=["a", "c"])) + right = Series( + [1], index=pd.MultiIndex.from_tuples([(1, 2, 3)], names=["a", "b", "c"]) + ) + result_left, result_right = left.align(right) + + expected_right = Series( + [1], index=pd.MultiIndex.from_tuples([(1, 3, 2)], names=["a", "c", "b"]) + ) + expected_left = Series( + [2], index=pd.MultiIndex.from_tuples([(1, 3, 2)], names=["a", "c", "b"]) + ) + tm.assert_series_equal(result_left, expected_left) + tm.assert_series_equal(result_right, expected_right) + + +def test_align_left_different_named_levels(): + # GH#45224 + left = Series( + [2], index=pd.MultiIndex.from_tuples([(1, 4, 3)], names=["a", "d", "c"]) + ) + right = Series( + [1], index=pd.MultiIndex.from_tuples([(1, 2, 3)], names=["a", "b", "c"]) + ) + result_left, result_right = left.align(right) + + expected_left = Series( + [2], index=pd.MultiIndex.from_tuples([(1, 3, 4, 2)], names=["a", "c", "d", "b"]) + ) + expected_right = Series( + [1], index=pd.MultiIndex.from_tuples([(1, 3, 4, 2)], names=["a", "c", "d", "b"]) + ) + tm.assert_series_equal(result_left, expected_left) + tm.assert_series_equal(result_right, expected_right) diff --git a/pandas/tests/series/test_arithmetic.py b/pandas/tests/series/test_arithmetic.py index 5fbb42789d746..5b3825fc0d388 100644 --- a/pandas/tests/series/test_arithmetic.py +++ b/pandas/tests/series/test_arithmetic.py @@ -887,8 +887,8 @@ def test_series_varied_multiindex_alignment(): expected = Series( [1000, 2001, 3002, 4003], index=pd.MultiIndex.from_tuples( - [("a", "x", 1), ("a", "x", 2), ("a", "y", 1), ("a", "y", 2)], - names=["ab", "xy", "num"], + [("x", 1, "a"), ("x", 2, "a"), ("y", 1, "a"), ("y", 2, "a")], + names=["xy", "num", "ab"], ), ) tm.assert_series_equal(result, expected)