From a0c82d83bed200225e57db96ecea110a7cf5208e Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:36:29 +0100 Subject: [PATCH] Backport PR #51950: BUG: Series.getitem not respecting CoW with MultiIndex --- doc/source/whatsnew/v2.0.0.rst | 3 +++ pandas/core/series.py | 2 ++ pandas/tests/copy_view/test_indexing.py | 12 ++++++++++++ 3 files changed, 17 insertions(+) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 58972e72c7094..f0998f35c1817 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -209,6 +209,9 @@ Copy-on-Write improvements - :meth:`DataFrame.__getitem__` will now respect the Copy-on-Write mechanism when the :class:`DataFrame` has :class:`MultiIndex` columns. +- :meth:`Series.__getitem__` will now respect the Copy-on-Write mechanism when the + :class:`Series` has a :class:`MultiIndex`. + - :meth:`Series.view` will now respect the Copy-on-Write mechanism. Copy-on-Write can be enabled through one of diff --git a/pandas/core/series.py b/pandas/core/series.py index 4ba63e05bae17..f20e5d7197afc 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1113,6 +1113,8 @@ def _get_value(self, label, takeable: bool = False): new_index = mi[loc] new_index = maybe_droplevels(new_index, label) new_ser = self._constructor(new_values, index=new_index, name=self.name) + if using_copy_on_write() and isinstance(loc, slice): + new_ser._mgr.add_references(self._mgr) # type: ignore[arg-type] return new_ser.__finalize__(self) else: diff --git a/pandas/tests/copy_view/test_indexing.py b/pandas/tests/copy_view/test_indexing.py index 238cda2e45457..caa137ec6a88e 100644 --- a/pandas/tests/copy_view/test_indexing.py +++ b/pandas/tests/copy_view/test_indexing.py @@ -1036,6 +1036,18 @@ def test_set_value_copy_only_necessary_column( assert np.shares_memory(get_array(df, "a"), get_array(view, "a")) +def test_series_midx_slice(using_copy_on_write): + ser = Series([1, 2, 3], index=pd.MultiIndex.from_arrays([[1, 1, 2], [3, 4, 5]])) + result = ser[1] + assert np.shares_memory(get_array(ser), get_array(result)) + result.iloc[0] = 100 + if using_copy_on_write: + expected = Series( + [1, 2, 3], index=pd.MultiIndex.from_arrays([[1, 1, 2], [3, 4, 5]]) + ) + tm.assert_series_equal(ser, expected) + + def test_getitem_midx_slice(using_copy_on_write, using_array_manager): df = DataFrame({("a", "x"): [1, 2], ("a", "y"): 1, ("b", "x"): 2}) df_orig = df.copy()