From 0ae4dfda05a18a9a6ab8049f54c19e28b0a3a582 Mon Sep 17 00:00:00 2001 From: Marco Edward Gorelli Date: Wed, 29 Nov 2023 19:00:48 +0100 Subject: [PATCH] BUG: DataFrame.update not operating in-place for datetime64[ns, UTC] dtype (#56228) * inplace update * copy-on-write fixups * Update doc/source/whatsnew/v2.2.0.rst --- doc/source/whatsnew/v2.2.0.rst | 2 +- pandas/core/frame.py | 14 ++++++-------- pandas/tests/frame/methods/test_update.py | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 16972ec1952a4..8cb4b3f24d435 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -521,7 +521,7 @@ Indexing Missing ^^^^^^^ -- +- Bug in :meth:`DataFrame.update` wasn't updating in-place for tz-aware datetime64 dtypes (:issue:`56227`) - MultiIndex diff --git a/pandas/core/frame.py b/pandas/core/frame.py index b6493614e05a0..f6c44827d1662 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -8852,14 +8852,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: @@ -8876,8 +8876,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") @@ -8911,7 +8909,7 @@ def update( if mask.all(): continue - self.loc[:, col] = expressions.where(mask, this, 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 0d32788b04b03..c79a37b5b30f0 100644 --- a/pandas/tests/frame/methods/test_update.py +++ b/pandas/tests/frame/methods/test_update.py @@ -140,6 +140,22 @@ 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, warn_copy_on_write): + # https://github.com/pandas-dev/pandas/issues/56227 + result = DataFrame([pd.Timestamp("2019", tz="UTC")]) + orig = result.copy() + view = result[:] + 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: + 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]})