From d5d737c4f1aeb56401e2922520b1487f5f28fa89 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 2 Aug 2019 11:59:41 -0700 Subject: [PATCH 1/3] BUG: fix replace_list --- pandas/core/generic.py | 5 ++- pandas/core/internals/managers.py | 7 +++-- pandas/tests/indexing/test_coercion.py | 43 ++++++++++---------------- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 821c35e0cce2f..2b783e3e7aaf8 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6658,9 +6658,8 @@ def replace( else: # need a non-zero len on all axes - for a in self._AXIS_ORDERS: - if not len(self._get_axis(a)): - return self + if not self.size: + return self new_data = self._data if is_dict_like(to_replace): diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index 8956821740bf3..b2019e3e59dda 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -7,7 +7,7 @@ import numpy as np -from pandas._libs import internals as libinternals, lib +from pandas._libs import Timedelta, Timestamp, internals as libinternals, lib from pandas.util._validators import validate_bool_kwarg from pandas.core.dtypes.cast import ( @@ -602,9 +602,10 @@ def comp(s, regex=False): """ if isna(s): return isna(values) - if hasattr(s, "asm8"): + if isinstance(s, (Timedelta, Timestamp)) and getattr(s, "tz", None) is None: + return _compare_or_regex_search( - maybe_convert_objects(values), getattr(s, "asm8"), regex + maybe_convert_objects(values), s.asm8, regex ) return _compare_or_regex_search(values, s, regex) diff --git a/pandas/tests/indexing/test_coercion.py b/pandas/tests/indexing/test_coercion.py index dea1d5114f1b9..c64d037916e5a 100644 --- a/pandas/tests/indexing/test_coercion.py +++ b/pandas/tests/indexing/test_coercion.py @@ -1029,17 +1029,15 @@ def test_replace_series(self, how, to_key, from_key): tm.assert_series_equal(result, exp) - # TODO(jbrockmendel) commented out to only have a single xfail printed - @pytest.mark.xfail( - reason="GH #18376, tzawareness-compat bug in BlockManager.replace_list" + @pytest.mark.parametrize("how", ["dict", "series"]) + @pytest.mark.parametrize( + "to_key", + ["timedelta64[ns]", "bool", "object", "complex128", "float64", "int64"], ) - # @pytest.mark.parametrize('how', ['dict', 'series']) - # @pytest.mark.parametrize('to_key', ['timedelta64[ns]', 'bool', 'object', - # 'complex128', 'float64', 'int64']) - # @pytest.mark.parametrize('from_key', ['datetime64[ns, UTC]', - # 'datetime64[ns, US/Eastern]']) - # def test_replace_series_datetime_tz(self, how, to_key, from_key): - def test_replace_series_datetime_tz(self): + @pytest.mark.parametrize( + "from_key", ["datetime64[ns, UTC]", "datetime64[ns, US/Eastern]"] + ) + def test_replace_series_datetime_tz(self, how, to_key, from_key): how = "series" from_key = "datetime64[ns, US/Eastern]" to_key = "timedelta64[ns]" @@ -1061,23 +1059,16 @@ def test_replace_series_datetime_tz(self): tm.assert_series_equal(result, exp) - # TODO(jreback) commented out to only have a single xfail printed - @pytest.mark.xfail( - reason="different tz, currently mask_missing raises SystemError", strict=False + @pytest.mark.parametrize("how", ["dict", "series"]) + @pytest.mark.parametrize( + "to_key", + ["datetime64[ns]", "datetime64[ns, UTC]", "datetime64[ns, US/Eastern]"], ) - # @pytest.mark.parametrize('how', ['dict', 'series']) - # @pytest.mark.parametrize('to_key', [ - # 'datetime64[ns]', 'datetime64[ns, UTC]', - # 'datetime64[ns, US/Eastern]']) - # @pytest.mark.parametrize('from_key', [ - # 'datetime64[ns]', 'datetime64[ns, UTC]', - # 'datetime64[ns, US/Eastern]']) - # def test_replace_series_datetime_datetime(self, how, to_key, from_key): - def test_replace_series_datetime_datetime(self): - how = "dict" - to_key = "datetime64[ns]" - from_key = "datetime64[ns]" - + @pytest.mark.parametrize( + "from_key", + ["datetime64[ns]", "datetime64[ns, UTC]", "datetime64[ns, US/Eastern]"], + ) + def test_replace_series_datetime_datetime(self, how, to_key, from_key): index = pd.Index([3, 4], name="xxx") obj = pd.Series(self.rep[from_key], index=index, name="yyy") assert obj.dtype == from_key From eea4a409e168a5d1defb356cfde0c693f38ae23b Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 2 Aug 2019 13:39:06 -0700 Subject: [PATCH 2/3] whatsnew --- doc/source/whatsnew/v0.25.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.1.rst b/doc/source/whatsnew/v0.25.1.rst index c80195af413f7..a4e792091cb4b 100644 --- a/doc/source/whatsnew/v0.25.1.rst +++ b/doc/source/whatsnew/v0.25.1.rst @@ -152,7 +152,7 @@ ExtensionArray Other ^^^^^ - +- Bug in :meth:`Series.replace` and :meth:`DataFrame.replace` when replacing timezone-aware timestamps using a dict-like replacer (:issue:`27720`) - - - From 557b5aa86d2ac928237887d689f8435e82125282 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 2 Aug 2019 15:01:16 -0700 Subject: [PATCH 3/3] change name xxx->xyz --- pandas/tests/indexing/test_coercion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/indexing/test_coercion.py b/pandas/tests/indexing/test_coercion.py index c64d037916e5a..ed80e249220fd 100644 --- a/pandas/tests/indexing/test_coercion.py +++ b/pandas/tests/indexing/test_coercion.py @@ -1042,7 +1042,7 @@ def test_replace_series_datetime_tz(self, how, to_key, from_key): from_key = "datetime64[ns, US/Eastern]" to_key = "timedelta64[ns]" - index = pd.Index([3, 4], name="xxx") + index = pd.Index([3, 4], name="xyz") obj = pd.Series(self.rep[from_key], index=index, name="yyy") assert obj.dtype == from_key @@ -1069,7 +1069,7 @@ def test_replace_series_datetime_tz(self, how, to_key, from_key): ["datetime64[ns]", "datetime64[ns, UTC]", "datetime64[ns, US/Eastern]"], ) def test_replace_series_datetime_datetime(self, how, to_key, from_key): - index = pd.Index([3, 4], name="xxx") + index = pd.Index([3, 4], name="xyz") obj = pd.Series(self.rep[from_key], index=index, name="yyy") assert obj.dtype == from_key