Skip to content

Commit 32de7c2

Browse files
committed
REF: simplify .map method for datetime-likes
1 parent fb754d7 commit 32de7c2

File tree

7 files changed

+17
-27
lines changed

7 files changed

+17
-27
lines changed

doc/source/whatsnew/v2.1.0.rst

+3
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,14 @@ Categorical
136136
Datetimelike
137137
^^^^^^^^^^^^
138138
- Bug in :meth:`Timestamp.round` with values close to the implementation bounds returning incorrect results instead of raising ``OutOfBoundsDatetime`` (:issue:`51494`)
139+
- :meth:`arrays.DatetimeArray.map` can now take a ``na_action`` argument. :meth:`DatetimeIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`)
139140
-
140141

141142
Timedelta
142143
^^^^^^^^^
143144
- Bug in :meth:`Timedelta.round` with values close to the implementation bounds returning incorrect results instead of raising ``OutOfBoundsTimedelta`` (:issue:`51494`)
144145
- Bug in :class:`TimedeltaIndex` division or multiplication leading to ``.freq`` of "0 Days" instead of ``None`` (:issue:`51575`)
146+
- :meth:`arrays.TimedeltaArray.map` can now take a ``na_action`` argument. :meth:`TimedeltaIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`)
145147
-
146148

147149
Timezones
@@ -193,6 +195,7 @@ Period
193195
^^^^^^
194196
- Bug in :class:`PeriodDtype` constructor failing to raise ``TypeError`` when no argument is passed or when ``None`` is passed (:issue:`27388`)
195197
- Bug in :class:`PeriodDtype` constructor raising ``ValueError`` instead of ``TypeError`` when an invalid type is passed (:issue:`51790`)
198+
- :meth:`arrays.PeriodArray.map` can now take a ``na_action`` argument. :meth:`PeriodIndex.map` with ``na_action="ignore"`` now works as expected. (:issue:`51644`)
196199
-
197200

198201
Plotting

pandas/core/algorithms.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1750,4 +1750,4 @@ def map_array(
17501750
if na_action is None:
17511751
return lib.map_infer(values, mapper)
17521752
else:
1753-
return lib.map_infer_mask(values, mapper, isna(values).view(np.uint8))
1753+
return lib.map_infer_mask(values, mapper, mask=isna(values).view(np.uint8))

pandas/core/arrays/datetimelike.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -752,13 +752,18 @@ def _unbox(self, other) -> np.int64 | np.datetime64 | np.timedelta64 | np.ndarra
752752

753753
@ravel_compat
754754
def map(self, mapper, na_action=None):
755-
if na_action is not None:
756-
raise NotImplementedError
757-
755+
# TODO(GH-23179): Add ExtensionArray.map
756+
# Need to figure out if we want ExtensionArray.map first.
757+
# If so, then we can refactor IndexOpsMixin._map_values to
758+
# a standalone function and call from here..
759+
# Else, just rewrite _map_infer_values to do the right thing.
758760
from pandas import Index
759761

760762
idx = Index(self)
763+
761764
try:
765+
if na_action is not None:
766+
raise ValueError("calling mapper directly only na_action=None")
762767
result = mapper(idx)
763768

764769
# Try to use this result if we can
@@ -768,7 +773,7 @@ def map(self, mapper, na_action=None):
768773
if not isinstance(result, Index):
769774
raise TypeError("The map function must return an Index object")
770775
except Exception:
771-
result = map_array(self, mapper)
776+
result = map_array(self, mapper, na_action=na_action)
772777
result = Index(result)
773778

774779
if isinstance(result, ABCMultiIndex):

pandas/core/base.py

-3
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,6 @@ def _map_values(self, mapper, na_action=None):
890890
if isinstance(arr, ExtensionArray):
891891
return arr.map(mapper, na_action=na_action)
892892

893-
# Argument 1 to "map_array" has incompatible type
894-
# "Union[IndexOpsMixin, ExtensionArray, ndarray[Any, Any]]";
895-
# expected "Union[ExtensionArray, ndarray[Any, Any]]"
896893
return algorithms.map_array(
897894
arr, mapper, na_action=na_action # type: ignore[arg-type]
898895
)

pandas/tests/apply/test_invalid_arg.py

-7
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,6 @@ def test_map_categorical_na_action():
8383
s.map(lambda x: x, na_action="ignore")
8484

8585

86-
def test_map_datetimetz_na_action():
87-
values = date_range("2011-01-01", "2011-01-02", freq="H").tz_localize("Asia/Tokyo")
88-
s = Series(values, name="XX")
89-
with pytest.raises(NotImplementedError, match=tm.EMPTY_STRING_PATTERN):
90-
s.map(lambda x: x, na_action="ignore")
91-
92-
9386
@pytest.mark.parametrize("method", ["apply", "agg", "transform"])
9487
@pytest.mark.parametrize("func", [{"A": {"B": "sum"}}, {"A": {"B": ["sum"]}}])
9588
def test_nested_renamer(frame_or_series, method, func):

pandas/tests/extension/test_datetime.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,8 @@ def test_combine_add(self, data_repeated):
118118

119119
@pytest.mark.parametrize("na_action", [None, "ignore"])
120120
def test_map(self, data, na_action):
121-
if na_action is not None:
122-
with pytest.raises(NotImplementedError, match=""):
123-
data.map(lambda x: x, na_action=na_action)
124-
else:
125-
result = data.map(lambda x: x, na_action=na_action)
126-
self.assert_extension_array_equal(result, data)
121+
result = data.map(lambda x: x, na_action=na_action)
122+
self.assert_extension_array_equal(result, data)
127123

128124

129125
class TestInterface(BaseDatetimeTests, base.BaseInterfaceTests):

pandas/tests/extension/test_period.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,8 @@ def test_diff(self, data, periods):
107107

108108
@pytest.mark.parametrize("na_action", [None, "ignore"])
109109
def test_map(self, data, na_action):
110-
if na_action is not None:
111-
with pytest.raises(NotImplementedError, match=""):
112-
data.map(lambda x: x, na_action=na_action)
113-
else:
114-
result = data.map(lambda x: x, na_action=na_action)
115-
self.assert_extension_array_equal(result, data)
110+
result = data.map(lambda x: x, na_action=na_action)
111+
self.assert_extension_array_equal(result, data)
116112

117113

118114
class TestInterface(BasePeriodTests, base.BaseInterfaceTests):

0 commit comments

Comments
 (0)