From 8e4b65c568737b223937add712df0cce64312366 Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 28 Nov 2023 15:51:29 +0000 Subject: [PATCH 1/3] inplace update --- doc/source/whatsnew/v2.2.0.rst | 2 +- pandas/core/frame.py | 18 ++++++++---------- pandas/tests/frame/methods/test_update.py | 13 +++++++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index dce776755ad7e..b54daee4ff326 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -520,7 +520,7 @@ Indexing Missing ^^^^^^^ -- +- Bug in :meth:`DataFrame.update` wasn't updating in-place for datetime64 dtypes (:issue:`56227`) - MultiIndex diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 5d05983529fba..91edae85ecdb2 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -8838,14 +8838,14 @@ def update( in the original dataframe. >>> df = pd.DataFrame({'A': [1, 2, 3], - ... 'B': [400, 500, 600]}) + ... 'B': [400., 500., 600.]}) >>> new_df = pd.DataFrame({'B': [4, np.nan, 6]}) >>> df.update(new_df) >>> df - A B - 0 1 4 - 1 2 500 - 2 3 6 + A B + 0 1 4.0 + 1 2 500.0 + 2 3 6.0 """ if not PYPY and using_copy_on_write(): if sys.getrefcount(self) <= REF_COUNT: @@ -8862,8 +8862,6 @@ def update( stacklevel=2, ) - from pandas.core.computation import expressions - # TODO: Support other joins if join != "left": # pragma: no cover raise NotImplementedError("Only left join is supported") @@ -8876,8 +8874,8 @@ def update( other = other.reindex(self.index) for col in self.columns.intersection(other.columns): - this = self[col]._values - that = other[col]._values + this = self[col] + that = other[col] if filter_func is not None: mask = ~filter_func(this) | isna(that) @@ -8897,7 +8895,7 @@ def update( if mask.all(): continue - self.loc[:, col] = expressions.where(mask, this, that) + self.loc[:, col] = this.where(mask, that) # ---------------------------------------------------------------------- # Data reshaping diff --git a/pandas/tests/frame/methods/test_update.py b/pandas/tests/frame/methods/test_update.py index 0d32788b04b03..2d5860f5b49e7 100644 --- a/pandas/tests/frame/methods/test_update.py +++ b/pandas/tests/frame/methods/test_update.py @@ -140,6 +140,19 @@ def test_update_datetime_tz(self): expected = DataFrame([pd.Timestamp("2019", tz="UTC")]) tm.assert_frame_equal(result, expected) + def test_update_datetime_tz_in_place(self, using_copy_on_write): + # https://github.com/pandas-dev/pandas/issues/56227 + result = DataFrame([pd.Timestamp("2019", tz="UTC")]) + orig = result.copy() + view = result[:] + result.update(result + pd.Timedelta(days=1)) + expected = DataFrame([pd.Timestamp("2019-01-02", tz="UTC")]) + tm.assert_frame_equal(result, expected) + if not using_copy_on_write: + tm.assert_frame_equal(view, expected) + else: + tm.assert_frame_equal(view, orig) + def test_update_with_different_dtype(self, using_copy_on_write): # GH#3217 df = DataFrame({"a": [1, 3], "b": [np.nan, 2]}) From 04eb8db88cd0f3f13b631714bf2233d00a7a7143 Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:50:27 +0000 Subject: [PATCH 2/3] copy-on-write fixups --- pandas/core/frame.py | 6 +++--- pandas/tests/frame/methods/test_update.py | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 91edae85ecdb2..3931616d49baf 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -8874,8 +8874,8 @@ def update( other = other.reindex(self.index) for col in self.columns.intersection(other.columns): - this = self[col] - that = other[col] + this = self[col]._values + that = other[col]._values if filter_func is not None: mask = ~filter_func(this) | isna(that) @@ -8895,7 +8895,7 @@ def update( if mask.all(): continue - self.loc[:, col] = this.where(mask, that) + self.loc[:, col] = self[col].where(mask, that) # ---------------------------------------------------------------------- # Data reshaping diff --git a/pandas/tests/frame/methods/test_update.py b/pandas/tests/frame/methods/test_update.py index 2d5860f5b49e7..c79a37b5b30f0 100644 --- a/pandas/tests/frame/methods/test_update.py +++ b/pandas/tests/frame/methods/test_update.py @@ -140,12 +140,15 @@ def test_update_datetime_tz(self): expected = DataFrame([pd.Timestamp("2019", tz="UTC")]) tm.assert_frame_equal(result, expected) - def test_update_datetime_tz_in_place(self, using_copy_on_write): + def test_update_datetime_tz_in_place(self, using_copy_on_write, warn_copy_on_write): # https://github.com/pandas-dev/pandas/issues/56227 result = DataFrame([pd.Timestamp("2019", tz="UTC")]) orig = result.copy() view = result[:] - result.update(result + pd.Timedelta(days=1)) + with tm.assert_produces_warning( + FutureWarning if warn_copy_on_write else None, match="Setting a value" + ): + result.update(result + pd.Timedelta(days=1)) expected = DataFrame([pd.Timestamp("2019-01-02", tz="UTC")]) tm.assert_frame_equal(result, expected) if not using_copy_on_write: From fed72ecc3aec8ab1289d2b58b61dadbf8c15c64f Mon Sep 17 00:00:00 2001 From: Marco Edward Gorelli Date: Tue, 28 Nov 2023 20:13:41 +0000 Subject: [PATCH 3/3] Update doc/source/whatsnew/v2.2.0.rst --- doc/source/whatsnew/v2.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index b54daee4ff326..90566f62bfdaf 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -520,7 +520,7 @@ Indexing Missing ^^^^^^^ -- Bug in :meth:`DataFrame.update` wasn't updating in-place for datetime64 dtypes (:issue:`56227`) +- Bug in :meth:`DataFrame.update` wasn't updating in-place for tz-aware datetime64 dtypes (:issue:`56227`) - MultiIndex