From 4c3d2a803afe43b08c5fe9a4ca1da42ea43581d1 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sun, 6 Jan 2019 22:24:35 -0800 Subject: [PATCH 1/2] BUG: DataFrame/Series.tz_localize/convert with copy=False does not mutate argument inplace --- doc/source/whatsnew/v0.24.0.rst | 1 + pandas/core/generic.py | 5 ++--- pandas/tests/frame/test_timezones.py | 16 ++++++++++++++++ pandas/tests/series/test_timezones.py | 16 ++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 4bc50695e1ecd..eb2c59f6a3519 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1596,6 +1596,7 @@ Timezones - Bug in :func:`to_datetime` where ``utc=True`` was not respected when passing a :class:`Timestamp` (:issue:`24415`) - Bug in :meth:`DataFrame.any` returns wrong value when ``axis=1`` and the data is of datetimelike type (:issue:`23070`) - Bug in :meth:`DatetimeIndex.to_period` where a timezone aware index was converted to UTC first before creating :class:`PeriodIndex` (:issue:`22905`) +- Bug in :meth:`DataFrame.tz_localize`, :meth:`DataFrame.tz_convert`, :meth:`Series.tz_localize`, and :meth:`Series.tz_convert` where ``copy=False`` would mutate the original argument inplace (:issue:`6326`) Offsets ^^^^^^^ diff --git a/pandas/core/generic.py b/pandas/core/generic.py index d271081aeaa51..769d26474b5dc 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9224,9 +9224,8 @@ def _tz_convert(ax, tz): if level not in (None, 0, ax.name): raise ValueError("The level {0} is not valid".format(level)) ax = _tz_convert(ax, tz) - result = self._constructor(self._data, copy=copy) - result.set_axis(ax, axis=axis, inplace=True) + result = result.set_axis(ax, axis=axis, inplace=False) return result.__finalize__(self) def tz_localize(self, tz, axis=0, level=None, copy=True, @@ -9390,7 +9389,7 @@ def _tz_localize(ax, tz, ambiguous, nonexistent): ax = _tz_localize(ax, tz, ambiguous, nonexistent) result = self._constructor(self._data, copy=copy) - result.set_axis(ax, axis=axis, inplace=True) + result = result.set_axis(ax, axis=axis, inplace=False) return result.__finalize__(self) # ---------------------------------------------------------------------- diff --git a/pandas/tests/frame/test_timezones.py b/pandas/tests/frame/test_timezones.py index f124a4c3f3570..fd6587c73b8fa 100644 --- a/pandas/tests/frame/test_timezones.py +++ b/pandas/tests/frame/test_timezones.py @@ -180,3 +180,19 @@ def test_boolean_compare_transpose_tzindex_with_dst(self, tz): result = df.T == df.T expected = DataFrame(True, index=list('ab'), columns=idx) tm.assert_frame_equal(result, expected) + + @pytest.mark.parametrize('copy', [True, False]) + @pytest.mark.parametrize('method, tz', [ + ['tz_localize', None], + ['tz_convert', 'Europe/Berlin'] + ]) + def test_tz_localize_convert_copy_inplace_mutate(self, copy, method, tz): + # GH 6326 + result = DataFrame(np.arange(0, 5), + index=date_range('20131027', periods=5, + freq='1H', tz=tz)) + getattr(result, method)('UTC', copy=copy) + expected = DataFrame(np.arange(0, 5), + index=date_range('20131027', periods=5, + freq='1H', tz=tz)) + tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/series/test_timezones.py b/pandas/tests/series/test_timezones.py index 7f49f94ef57ce..ec644a8e93da2 100644 --- a/pandas/tests/series/test_timezones.py +++ b/pandas/tests/series/test_timezones.py @@ -348,3 +348,19 @@ def test_series_truncate_datetimeindex_tz(self): result = s.truncate(datetime(2005, 4, 2), datetime(2005, 4, 4)) expected = Series([1, 2, 3], index=idx[1:4]) tm.assert_series_equal(result, expected) + + @pytest.mark.parametrize('copy', [True, False]) + @pytest.mark.parametrize('method, tz', [ + ['tz_localize', None], + ['tz_convert', 'Europe/Berlin'] + ]) + def test_tz_localize_convert_copy_inplace_mutate(self, copy, method, tz): + # GH 6326 + result = Series(np.arange(0, 5), + index=date_range('20131027', periods=5, freq='1H', + tz=tz)) + getattr(result, method)('UTC', copy=copy) + expected = Series(np.arange(0, 5), + index=date_range('20131027', periods=5, freq='1H', + tz=tz)) + tm.assert_series_equal(result, expected) From c7bfdab32940e02ad6177f060d4f12a3b0a4d463 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sun, 6 Jan 2019 22:29:03 -0800 Subject: [PATCH 2/2] Put back space --- pandas/core/generic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 769d26474b5dc..1e6ae71660617 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9224,6 +9224,7 @@ def _tz_convert(ax, tz): if level not in (None, 0, ax.name): raise ValueError("The level {0} is not valid".format(level)) ax = _tz_convert(ax, tz) + result = self._constructor(self._data, copy=copy) result = result.set_axis(ax, axis=axis, inplace=False) return result.__finalize__(self)