Skip to content

Commit 8d48f02

Browse files
authored
BUG: freq invalidation in DatetimeIndex.where (#62850)
1 parent a668459 commit 8d48f02

File tree

3 files changed

+21
-4
lines changed

3 files changed

+21
-4
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ Datetimelike
980980
- Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` does not raise on Custom business days frequencies bigger then "1C" (:issue:`58664`)
981981
- Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` returning ``False`` on double-digit frequencies (:issue:`58523`)
982982
- Bug in :meth:`DatetimeIndex.union` and :meth:`DatetimeIndex.intersection` when ``unit`` was non-nanosecond (:issue:`59036`)
983+
- Bug in :meth:`DatetimeIndex.where` and :meth:`TimedeltaIndex.where` failing to set ``freq=None`` in some cases (:issue:`24555`)
983984
- Bug in :meth:`Index.union` with a ``pyarrow`` timestamp dtype incorrectly returning ``object`` dtype (:issue:`58421`)
984985
- Bug in :meth:`Series.dt.microsecond` producing incorrect results for pyarrow backed :class:`Series`. (:issue:`59154`)
985986
- Bug in :meth:`Timestamp.normalize` and :meth:`DatetimeArray.normalize` returning incorrect results instead of raising on integer overflow for very small (distant past) values (:issue:`60583`)
@@ -996,7 +997,6 @@ Datetimelike
996997
- Bug in constructing arrays with a timezone-aware :class:`ArrowDtype` from timezone-naive datetime objects incorrectly treating those as UTC times instead of wall times like :class:`DatetimeTZDtype` (:issue:`61775`)
997998
- Bug in setting scalar values with mismatched resolution into arrays with non-nanosecond ``datetime64``, ``timedelta64`` or :class:`DatetimeTZDtype` incorrectly truncating those scalars (:issue:`56410`)
998999

999-
10001000
Timedelta
10011001
^^^^^^^^^
10021002
- Accuracy improvement in :meth:`Timedelta.to_pytimedelta` to round microseconds consistently for large nanosecond based Timedelta (:issue:`57841`)

pandas/core/arrays/datetimelike.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,9 @@ def __getitem__(self, key: PositionalIndexer2D) -> Self | DTScalarOrNaT:
393393
else:
394394
# At this point we know the result is an array.
395395
result = cast(Self, result)
396-
result._freq = self._get_getitem_freq(key)
396+
# error: Incompatible types in assignment (expression has type
397+
# "BaseOffset | None", variable has type "None")
398+
result._freq = self._get_getitem_freq(key) # type: ignore[assignment]
397399
return result
398400

399401
def _get_getitem_freq(self, key) -> BaseOffset | None:
@@ -527,6 +529,10 @@ def view(self, dtype: Dtype | None = None) -> ArrayLike:
527529
# are present in this file.
528530
return super().view(dtype)
529531

532+
def _putmask(self, mask: npt.NDArray[np.bool_], value) -> None:
533+
super()._putmask(mask, value)
534+
self._freq = None # GH#24555
535+
530536
# ------------------------------------------------------------------
531537
# Validation Methods
532538
# TODO: try to de-duplicate these, ensure identical behavior
@@ -2042,7 +2048,7 @@ def _maybe_pin_freq(self, freq, validate_kwds: dict) -> None:
20422048
if self._freq is None:
20432049
# Set _freq directly to bypass duplicative _validate_frequency
20442050
# check.
2045-
self._freq = to_offset(self.inferred_freq)
2051+
self._freq = to_offset(self.inferred_freq) # type: ignore[assignment]
20462052
elif freq is lib.no_default:
20472053
# user did not specify anything, keep inferred freq if the original
20482054
# data had one, otherwise do nothing
@@ -2442,7 +2448,7 @@ def take(
24422448

24432449
if isinstance(maybe_slice, slice):
24442450
freq = self._get_getitem_freq(maybe_slice)
2445-
result._freq = freq
2451+
result._freq = freq # type: ignore[assignment]
24462452

24472453
return result
24482454

pandas/tests/indexes/datetimes/test_indexing.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ def test_getitem_int_list(self):
119119

120120

121121
class TestWhere:
122+
@pytest.mark.parametrize("is_td", [True, False])
123+
def test_where_freq_invalidation(self, is_td):
124+
# GH#24555
125+
index = date_range("20130101", periods=3, tz="US/Eastern")
126+
if is_td:
127+
index = index - index[0]
128+
other = Index([pd.NaT, pd.NaT] + index[2:].tolist())
129+
130+
result = index.where(notna(other), other)
131+
assert result.freq is None
132+
122133
def test_where_doesnt_retain_freq(self):
123134
dti = date_range("20130101", periods=3, freq="D", name="idx")
124135
cond = [True, True, False]

0 commit comments

Comments
 (0)