diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 7fc856be374e9..9ceec88e494a5 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -222,6 +222,7 @@ Copy-on-Write improvements - :meth:`DataFrame.to_timestamp` / :meth:`Series.to_timestamp` - :meth:`DataFrame.to_period` / :meth:`Series.to_period` - :meth:`DataFrame.truncate` + - :meth:`DataFrame.iterrows` - :meth:`DataFrame.tz_convert` / :meth:`Series.tz_localize` - :meth:`DataFrame.fillna` / :meth:`Series.fillna` - :meth:`DataFrame.interpolate` / :meth:`Series.interpolate` diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 71dc3b523fca6..4154def5a7b77 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1392,8 +1392,14 @@ def iterrows(self) -> Iterable[tuple[Hashable, Series]]: """ columns = self.columns klass = self._constructor_sliced + using_cow = using_copy_on_write() for k, v in zip(self.index, self.values): s = klass(v, index=columns, name=k).__finalize__(self) + if using_cow and self._mgr.is_single_block: + s._mgr.blocks[0].refs = self._mgr.blocks[0].refs # type: ignore[union-attr] # noqa + s._mgr.blocks[0].refs.add_reference( # type: ignore[union-attr] + s._mgr.blocks[0] # type: ignore[arg-type, union-attr] + ) yield k, s def itertuples( diff --git a/pandas/tests/copy_view/test_methods.py b/pandas/tests/copy_view/test_methods.py index 91419ba415fda..320b840cfa561 100644 --- a/pandas/tests/copy_view/test_methods.py +++ b/pandas/tests/copy_view/test_methods.py @@ -1329,6 +1329,16 @@ def test_asfreq_noop(using_copy_on_write): tm.assert_frame_equal(df, df_orig) +def test_iterrows(using_copy_on_write): + df = DataFrame({"a": 0, "b": 1}, index=[1, 2, 3]) + df_orig = df.copy() + + for _, sub in df.iterrows(): + sub.iloc[0] = 100 + if using_copy_on_write: + tm.assert_frame_equal(df, df_orig) + + def test_interpolate_creates_copy(using_copy_on_write): # GH#51126 df = DataFrame({"a": [1.5, np.nan, 3]})