From 8e06eb7660f67c439482c7a109e366f8f275f228 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Sun, 12 Mar 2023 20:17:51 +0000 Subject: [PATCH 1/3] REF: simplify .map method for datetime-likes --- doc/source/whatsnew/v2.1.0.rst | 5 +++++ pandas/core/arrays/datetimelike.py | 5 +---- pandas/core/base.py | 3 --- pandas/tests/apply/test_invalid_arg.py | 7 ------- pandas/tests/extension/test_datetime.py | 8 ++------ pandas/tests/extension/test_period.py | 8 ++------ 6 files changed, 10 insertions(+), 26 deletions(-) diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index c6783e46faaee..b79d778db3744 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -140,13 +140,17 @@ Categorical Datetimelike ^^^^^^^^^^^^ - Bug in :meth:`Timestamp.round` with values close to the implementation bounds returning incorrect results instead of raising ``OutOfBoundsDatetime`` (:issue:`51494`) +- :meth:`arrays.DatetimeArray.map` can now take a ``na_action`` argument. :meth:`DatetimeIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`) - Bug in :meth:`arrays.DatetimeArray.map` and :meth:`DatetimeIndex.map`, where the supplied callable operated array-wise instead of element-wise (:issue:`51977`) +- Timedelta ^^^^^^^^^ - Bug in :meth:`Timedelta.round` with values close to the implementation bounds returning incorrect results instead of raising ``OutOfBoundsTimedelta`` (:issue:`51494`) - Bug in :class:`TimedeltaIndex` division or multiplication leading to ``.freq`` of "0 Days" instead of ``None`` (:issue:`51575`) +- :meth:`arrays.TimedeltaArray.map` can now take a ``na_action`` argument. :meth:`TimedeltaIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`) - Bug in :meth:`arrays.TimedeltaArray.map` and :meth:`TimedeltaIndex.map`, where the supplied callable operated array-wise instead of element-wise (:issue:`51977`) +- Timezones ^^^^^^^^^ @@ -197,6 +201,7 @@ Period ^^^^^^ - Bug in :class:`PeriodDtype` constructor failing to raise ``TypeError`` when no argument is passed or when ``None`` is passed (:issue:`27388`) - Bug in :class:`PeriodDtype` constructor raising ``ValueError`` instead of ``TypeError`` when an invalid type is passed (:issue:`51790`) +- :meth:`arrays.PeriodArray.map` can now take a ``na_action`` argument. :meth:`PeriodIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`) - Bug in :meth:`arrays.PeriodArray.map` and :meth:`PeriodIndex.map`, where the supplied callable operated array-wise instead of element-wise (:issue:`51977`) - diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 2d2be0a07c0e0..90771eca6fdf1 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -747,12 +747,9 @@ def _unbox(self, other) -> np.int64 | np.datetime64 | np.timedelta64 | np.ndarra @ravel_compat def map(self, mapper, na_action=None): - if na_action is not None: - raise NotImplementedError - from pandas import Index - result = map_array(self, mapper) + result = map_array(self, mapper, na_action=na_action) result = Index(result) if isinstance(result, ABCMultiIndex): diff --git a/pandas/core/base.py b/pandas/core/base.py index dc37550ced387..27e8ca8087647 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -894,9 +894,6 @@ def _map_values(self, mapper, na_action=None, convert: bool = True): if isinstance(arr, ExtensionArray): return arr.map(mapper, na_action=na_action) - # Argument 1 to "map_array" has incompatible type - # "Union[IndexOpsMixin, ExtensionArray, ndarray[Any, Any]]"; - # expected "Union[ExtensionArray, ndarray[Any, Any]]" return algorithms.map_array( arr, mapper, na_action=na_action, convert=convert # type: ignore[arg-type] ) diff --git a/pandas/tests/apply/test_invalid_arg.py b/pandas/tests/apply/test_invalid_arg.py index 294693df7340a..0207391c3070a 100644 --- a/pandas/tests/apply/test_invalid_arg.py +++ b/pandas/tests/apply/test_invalid_arg.py @@ -83,13 +83,6 @@ def test_map_categorical_na_action(): s.map(lambda x: x, na_action="ignore") -def test_map_datetimetz_na_action(): - values = date_range("2011-01-01", "2011-01-02", freq="H").tz_localize("Asia/Tokyo") - s = Series(values, name="XX") - with pytest.raises(NotImplementedError, match=tm.EMPTY_STRING_PATTERN): - s.map(lambda x: x, na_action="ignore") - - @pytest.mark.parametrize("method", ["apply", "agg", "transform"]) @pytest.mark.parametrize("func", [{"A": {"B": "sum"}}, {"A": {"B": ["sum"]}}]) def test_nested_renamer(frame_or_series, method, func): diff --git a/pandas/tests/extension/test_datetime.py b/pandas/tests/extension/test_datetime.py index 21f4f949cdfa9..a93271a454459 100644 --- a/pandas/tests/extension/test_datetime.py +++ b/pandas/tests/extension/test_datetime.py @@ -118,12 +118,8 @@ def test_combine_add(self, data_repeated): @pytest.mark.parametrize("na_action", [None, "ignore"]) def test_map(self, data, na_action): - if na_action is not None: - with pytest.raises(NotImplementedError, match=""): - data.map(lambda x: x, na_action=na_action) - else: - result = data.map(lambda x: x, na_action=na_action) - self.assert_extension_array_equal(result, data) + result = data.map(lambda x: x, na_action=na_action) + self.assert_extension_array_equal(result, data) class TestInterface(BaseDatetimeTests, base.BaseInterfaceTests): diff --git a/pandas/tests/extension/test_period.py b/pandas/tests/extension/test_period.py index 4be761358ba15..0c961a8563a6e 100644 --- a/pandas/tests/extension/test_period.py +++ b/pandas/tests/extension/test_period.py @@ -107,12 +107,8 @@ def test_diff(self, data, periods): @pytest.mark.parametrize("na_action", [None, "ignore"]) def test_map(self, data, na_action): - if na_action is not None: - with pytest.raises(NotImplementedError, match=""): - data.map(lambda x: x, na_action=na_action) - else: - result = data.map(lambda x: x, na_action=na_action) - self.assert_extension_array_equal(result, data) + result = data.map(lambda x: x, na_action=na_action) + self.assert_extension_array_equal(result, data) class TestInterface(BasePeriodTests, base.BaseInterfaceTests): From b84402b103b58ad682a4e57a1f7e730df00bf0ea Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Mon, 13 Mar 2023 19:15:30 +0000 Subject: [PATCH 2/3] sort issue numbers --- doc/source/whatsnew/v2.1.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index b79d778db3744..4e4ac14c37961 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -200,8 +200,8 @@ I/O Period ^^^^^^ - Bug in :class:`PeriodDtype` constructor failing to raise ``TypeError`` when no argument is passed or when ``None`` is passed (:issue:`27388`) -- Bug in :class:`PeriodDtype` constructor raising ``ValueError`` instead of ``TypeError`` when an invalid type is passed (:issue:`51790`) - :meth:`arrays.PeriodArray.map` can now take a ``na_action`` argument. :meth:`PeriodIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`) +- Bug in :class:`PeriodDtype` constructor raising ``ValueError`` instead of ``TypeError`` when an invalid type is passed (:issue:`51790`) - Bug in :meth:`arrays.PeriodArray.map` and :meth:`PeriodIndex.map`, where the supplied callable operated array-wise instead of element-wise (:issue:`51977`) - From 2fa02aa49708ae544af4911f5e24ac41315b7201 Mon Sep 17 00:00:00 2001 From: Terji Petersen Date: Tue, 14 Mar 2023 18:37:21 +0000 Subject: [PATCH 3/3] fix comment --- pandas/core/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pandas/core/base.py b/pandas/core/base.py index 27e8ca8087647..96209ba97c0aa 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -894,6 +894,9 @@ def _map_values(self, mapper, na_action=None, convert: bool = True): if isinstance(arr, ExtensionArray): return arr.map(mapper, na_action=na_action) + # Argument 1 to "map_array" has incompatible type + # "Union[IndexOpsMixin, ndarray[Any, Any]]"; + # expected "Union[ExtensionArray, ndarray[Any, Any]] return algorithms.map_array( arr, mapper, na_action=na_action, convert=convert # type: ignore[arg-type] )