From 110ff56836347d2564ac9f721fd09b21abb77e73 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Sun, 12 Aug 2018 00:35:47 +0200 Subject: [PATCH] ENH: add inplace-kwarg to df.update --- doc/source/whatsnew/v0.24.0.txt | 1 + pandas/core/frame.py | 21 +++++++++++++++++---- pandas/tests/frame/test_combine_concat.py | 15 ++++++++++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 317b8b8878308..16780abab565b 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -183,6 +183,7 @@ Other Enhancements - :class:`Series` and :class:`DataFrame` now support :class:`Iterable` in constructor (:issue:`2193`) - :class:`DatetimeIndex` gained :attr:`DatetimeIndex.timetz` attribute. Returns local time with timezone information. (:issue:`21358`) - :class:`Resampler` now is iterable like :class:`GroupBy` (:issue:`15314`). +- :meth:`DataFrame.update` has gained an ``inplace``-kwarg, which defaults to True (same behavior as before). (:issue:`21858`) - :ref:`Series.resample` and :ref:`DataFrame.resample` have gained the :meth:`Resampler.quantile` (:issue:`15023`). .. _whatsnew_0240.api_breaking: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 052952103e28c..2cfb06c8d053c 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -5078,7 +5078,7 @@ def combiner(x, y, needs_i8_conversion=False): return self.combine(other, combiner, overwrite=False) def update(self, other, join='left', overwrite=True, filter_func=None, - raise_conflict=False): + raise_conflict=False, inplace=True): """ Modify in place using non-NA values from another DataFrame. @@ -5108,6 +5108,11 @@ def update(self, other, join='left', overwrite=True, filter_func=None, raise_conflict : bool, default False If True, will raise a ValueError if the DataFrame and `other` both contain non-NA data in the same place. + inplace : bool, default True + If True, updates the DataFrame inplace. If False, returns a new + DataFrame. + + .. versionadded:: 0.24.0 Raises ------ @@ -5189,8 +5194,13 @@ def update(self, other, join='left', overwrite=True, filter_func=None, other = other.reindex_like(self) - for col in self.columns: - this = self[col].values + if inplace: + frame = self + else: + frame = self.copy() + + for col in frame.columns: + this = frame[col].values that = other[col].values if filter_func is not None: with np.errstate(all='ignore'): @@ -5211,7 +5221,10 @@ def update(self, other, join='left', overwrite=True, filter_func=None, if mask.all(): continue - self[col] = expressions.where(mask, this, that) + frame[col] = expressions.where(mask, this, that) + + if not inplace: + return frame # ---------------------------------------------------------------------- # Data reshaping diff --git a/pandas/tests/frame/test_combine_concat.py b/pandas/tests/frame/test_combine_concat.py index 15ca65395e4fc..d9997a1a2cf69 100644 --- a/pandas/tests/frame/test_combine_concat.py +++ b/pandas/tests/frame/test_combine_concat.py @@ -4,6 +4,8 @@ from datetime import datetime +import pytest + import numpy as np from numpy import nan @@ -198,7 +200,8 @@ def test_append_dtypes(self): expected = DataFrame({'bar': Series([Timestamp('20130101'), 1])}) assert_frame_equal(result, expected) - def test_update(self): + @pytest.mark.parametrize('inplace', [True, False]) + def test_update(self, inplace): df = DataFrame([[1.5, nan, 3.], [1.5, nan, 3.], [1.5, nan, 3], @@ -207,13 +210,19 @@ def test_update(self): other = DataFrame([[3.6, 2., np.nan], [np.nan, np.nan, 7]], index=[1, 3]) - df.update(other) + if inplace: + df.update(other, inplace=inplace) + result = df + else: + orig = df.copy() + result = df.update(other, inplace=inplace) + assert_frame_equal(df, orig) expected = DataFrame([[1.5, nan, 3], [3.6, 2, 3], [1.5, nan, 3], [1.5, nan, 7.]]) - assert_frame_equal(df, expected) + assert_frame_equal(result, expected) def test_update_dtypes(self):