Skip to content

Commit 4354b66

Browse files
Backport PR pandas-dev#44839: REGR: allow reindexing datetimelike with upcast / raise deprecation warning (pandas-dev#45406)
Co-authored-by: Joris Van den Bossche <[email protected]>
1 parent af65e0c commit 4354b66

File tree

5 files changed

+35
-1
lines changed

5 files changed

+35
-1
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ Datetimelike
784784
- Bug in :meth:`Index.insert` for inserting ``np.datetime64``, ``np.timedelta64`` or ``tuple`` into :class:`Index` with ``dtype='object'`` with negative loc adding ``None`` and replacing existing value (:issue:`44509`)
785785
- Bug in :meth:`Timestamp.to_pydatetime` failing to retain the ``fold`` attribute (:issue:`45087`)
786786
- Bug in :meth:`Series.mode` with ``DatetimeTZDtype`` incorrectly returning timezone-naive and ``PeriodDtype`` incorrectly raising (:issue:`41927`)
787+
- Fixed regression in :meth:`~Series.reindex` raising an error when using an incompatible fill value with a datetime-like dtype (or not raising a deprecation warning for using a ``datetime.date`` as fill value) (:issue:`42921`)
787788
- Bug in :class:`DateOffset`` addition with :class:`Timestamp` where ``offset.nanoseconds`` would not be included in the result (:issue:`43968`, :issue:`36589`)
788789
- Bug in :meth:`Timestamp.fromtimestamp` not supporting the ``tz`` argument (:issue:`45083`)
789790
- Bug in :class:`DataFrame` construction from dict of :class:`Series` with mismatched index dtypes sometimes raising depending on the ordering of the passed dict (:issue:`44091`)

pandas/core/array_algos/take.py

+6
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ def take_nd(
9494
"""
9595
if fill_value is lib.no_default:
9696
fill_value = na_value_for_dtype(arr.dtype, compat=False)
97+
elif isinstance(arr.dtype, np.dtype) and arr.dtype.kind in "mM":
98+
dtype, fill_value = maybe_promote(arr.dtype, fill_value)
99+
if arr.dtype != dtype:
100+
# EA.take is strict about returning a new object of the same type
101+
# so for that case cast upfront
102+
arr = arr.astype(dtype)
97103

98104
if not isinstance(arr, np.ndarray):
99105
# i.e. ExtensionArray,

pandas/core/dtypes/cast.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ def _maybe_promote(dtype: np.dtype, fill_value=np.nan):
575575
except (ValueError, TypeError):
576576
pass
577577
else:
578-
if fv.tz is None:
578+
if isna(fv) or fv.tz is None:
579579
return dtype, fv.asm8
580580

581581
return np.dtype("object"), fill_value

pandas/tests/frame/methods/test_reindex.py

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import pytest
99

1010
from pandas._libs.tslibs.timezones import dateutil_gettz as gettz
11+
import pandas.util._test_decorators as td
1112

1213
import pandas as pd
1314
from pandas import (
@@ -133,6 +134,7 @@ def test_reindex_copies(self):
133134
result2 = df.reindex(columns=cols, index=df.index, copy=True)
134135
assert not np.shares_memory(result2[0]._values, df[0]._values)
135136

137+
@td.skip_array_manager_not_yet_implemented
136138
def test_reindex_date_fill_value(self):
137139
# passing date to dt64 is deprecated
138140
arr = date_range("2016-01-01", periods=6).values.reshape(3, 2)
@@ -149,6 +151,11 @@ def test_reindex_date_fill_value(self):
149151
)
150152
tm.assert_frame_equal(res, expected)
151153

154+
# only reindexing rows
155+
with tm.assert_produces_warning(FutureWarning):
156+
res = df.reindex(index=range(4), fill_value=fv)
157+
tm.assert_frame_equal(res, expected[["A", "B"]])
158+
152159
# same with a datetime-castable str
153160
res = df.reindex(
154161
index=range(4), columns=["A", "B", "C"], fill_value="2016-01-01"

pandas/tests/series/methods/test_reindex.py

+20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
Period,
1010
PeriodIndex,
1111
Series,
12+
Timedelta,
13+
Timestamp,
1214
date_range,
1315
isna,
1416
)
@@ -296,6 +298,24 @@ def test_reindex_fill_value():
296298
tm.assert_series_equal(result, expected)
297299

298300

301+
@pytest.mark.parametrize("dtype", ["datetime64[ns]", "timedelta64[ns]"])
302+
@pytest.mark.parametrize("fill_value", ["string", 0, Timedelta(0)])
303+
def test_reindex_fill_value_datetimelike_upcast(dtype, fill_value, using_array_manager):
304+
# https://github.com/pandas-dev/pandas/issues/42921
305+
if using_array_manager:
306+
pytest.skip("Array manager does not promote dtype, hence we fail")
307+
308+
if dtype == "timedelta64[ns]" and fill_value == Timedelta(0):
309+
# use the scalar that is not compatible with the dtype for this test
310+
fill_value = Timestamp(0)
311+
312+
ser = Series([NaT], dtype=dtype)
313+
314+
result = ser.reindex([0, 1], fill_value=fill_value)
315+
expected = Series([None, fill_value], index=[0, 1], dtype=object)
316+
tm.assert_series_equal(result, expected)
317+
318+
299319
def test_reindex_datetimeindexes_tz_naive_and_aware():
300320
# GH 8306
301321
idx = date_range("20131101", tz="America/Chicago", periods=7)

0 commit comments

Comments
 (0)