Skip to content

Commit 5dab6ad

Browse files
authored
DEPR: unit keyword in TimedeltaIndex (#55856)
* DEPR: unit keyword in TimedeltaIndex * update docstring * update doctest
1 parent 09cb367 commit 5dab6ad

File tree

10 files changed

+47
-21
lines changed

10 files changed

+47
-21
lines changed

doc/source/whatsnew/v2.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ Other Deprecations
401401
- Deprecated the ``fastpath`` keyword in the :class:`Series` constructor (:issue:`20110`)
402402
- Deprecated the ``kind`` keyword in :meth:`Series.resample` and :meth:`DataFrame.resample`, explicitly cast the object's ``index`` instead (:issue:`55895`)
403403
- Deprecated the ``ordinal`` keyword in :class:`PeriodIndex`, use :meth:`PeriodIndex.from_ordinals` instead (:issue:`55960`)
404+
- Deprecated the ``unit`` keyword in :class:`TimedeltaIndex` construction, use :func:`to_timedelta` instead (:issue:`55499`)
404405
- Deprecated the behavior of :meth:`Series.value_counts` and :meth:`Index.value_counts` with object dtype; in a future version these will not perform dtype inference on the resulting :class:`Index`, do ``result.index = result.index.infer_objects()`` to retain the old behavior (:issue:`56161`)
405406
- Deprecated the extension test classes ``BaseNoReduceTests``, ``BaseBooleanReduceTests``, and ``BaseNumericReduceTests``, use ``BaseReduceTests`` instead (:issue:`54663`)
406407
- Deprecated the option ``mode.data_manager`` and the ``ArrayManager``; only the ``BlockManager`` will be available in future versions (:issue:`55043`)

pandas/core/indexes/timedeltas.py

+18-6
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ class TimedeltaIndex(DatetimeTimedeltaMixin):
6363
Optional timedelta-like data to construct index with.
6464
unit : {'D', 'h', 'm', 's', 'ms', 'us', 'ns'}, optional
6565
The unit of ``data``.
66+
67+
.. deprecated:: 2.2.0
68+
Use ``pd.to_timedelta`` instead.
69+
6670
freq : str or pandas offset object, optional
6771
One of pandas date offset strings or corresponding objects. The string
6872
``'infer'`` can be passed in order to set the frequency of the index as
@@ -113,13 +117,9 @@ class TimedeltaIndex(DatetimeTimedeltaMixin):
113117
TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'],
114118
dtype='timedelta64[ns]', freq=None)
115119
116-
>>> pd.TimedeltaIndex([1, 2, 4, 8], unit='D')
117-
TimedeltaIndex(['1 days', '2 days', '4 days', '8 days'],
118-
dtype='timedelta64[ns]', freq=None)
119-
120120
We can also let pandas infer the frequency when possible.
121121
122-
>>> pd.TimedeltaIndex(range(5), unit='D', freq='infer')
122+
>>> pd.TimedeltaIndex(np.arange(5) * 24 * 3600 * 1e9, freq='infer')
123123
TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'],
124124
dtype='timedelta64[ns]', freq='D')
125125
"""
@@ -149,7 +149,7 @@ def _resolution_obj(self) -> Resolution | None: # type: ignore[override]
149149
def __new__(
150150
cls,
151151
data=None,
152-
unit=None,
152+
unit=lib.no_default,
153153
freq=lib.no_default,
154154
closed=lib.no_default,
155155
dtype=None,
@@ -165,6 +165,18 @@ def __new__(
165165
stacklevel=find_stack_level(),
166166
)
167167

168+
if unit is not lib.no_default:
169+
# GH#55499
170+
warnings.warn(
171+
f"The 'unit' keyword in {cls.__name__} construction is "
172+
"deprecated and will be removed in a future version. "
173+
"Use pd.to_timedelta instead.",
174+
FutureWarning,
175+
stacklevel=find_stack_level(),
176+
)
177+
else:
178+
unit = None
179+
168180
name = maybe_extract_name(name, data, cls)
169181

170182
if is_scalar(data):

pandas/core/tools/timedeltas.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,5 +279,5 @@ def _convert_listlike(
279279

280280
from pandas import TimedeltaIndex
281281

282-
value = TimedeltaIndex(td64arr, unit="ns", name=name)
282+
value = TimedeltaIndex(td64arr, name=name)
283283
return value

pandas/tests/arrays/test_datetimelike.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def test_concat_same_type(self, arr1d):
217217

218218
result = arr._concat_same_type([arr[:-1], arr[1:], arr])
219219
arr2 = arr.astype(object)
220-
expected = self.index_cls(np.concatenate([arr2[:-1], arr2[1:], arr2]), None)
220+
expected = self.index_cls(np.concatenate([arr2[:-1], arr2[1:], arr2]))
221221

222222
tm.assert_index_equal(self.index_cls(result), expected)
223223

@@ -1247,7 +1247,7 @@ def test_to_numpy_extra(arr):
12471247
"values",
12481248
[
12491249
pd.to_datetime(["2020-01-01", "2020-02-01"]),
1250-
TimedeltaIndex([1, 2], unit="D"),
1250+
pd.to_timedelta([1, 2], unit="D"),
12511251
PeriodIndex(["2020-01-01", "2020-02-01"], freq="D"),
12521252
],
12531253
)
@@ -1278,7 +1278,7 @@ def test_searchsorted_datetimelike_with_listlike(values, klass, as_index):
12781278
"values",
12791279
[
12801280
pd.to_datetime(["2020-01-01", "2020-02-01"]),
1281-
TimedeltaIndex([1, 2], unit="D"),
1281+
pd.to_timedelta([1, 2], unit="D"),
12821282
PeriodIndex(["2020-01-01", "2020-02-01"], freq="D"),
12831283
],
12841284
)

pandas/tests/indexes/test_datetimelike.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,5 @@ def test_diff(self, unit):
165165
# GH 55080
166166
dti = pd.to_datetime([10, 20, 30], unit=unit).as_unit(unit)
167167
result = dti.diff(1)
168-
expected = pd.TimedeltaIndex([pd.NaT, 10, 10], unit=unit).as_unit(unit)
168+
expected = pd.to_timedelta([pd.NaT, 10, 10], unit=unit).as_unit(unit)
169169
tm.assert_index_equal(result, expected)

pandas/tests/indexes/timedeltas/test_constructors.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ def test_array_of_dt64_nat_raises(self):
3939
@pytest.mark.parametrize("unit", ["Y", "y", "M"])
4040
def test_unit_m_y_raises(self, unit):
4141
msg = "Units 'M', 'Y', and 'y' are no longer supported"
42+
depr_msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
4243
with pytest.raises(ValueError, match=msg):
43-
TimedeltaIndex([1, 3, 7], unit)
44+
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
45+
TimedeltaIndex([1, 3, 7], unit)
4446

4547
def test_int64_nocopy(self):
4648
# GH#23539 check that a copy isn't made when we pass int64 data
@@ -120,7 +122,7 @@ def test_float64_ns_rounded(self):
120122

121123
def test_float64_unit_conversion(self):
122124
# GH#23539
123-
tdi = TimedeltaIndex([1.5, 2.25], unit="D")
125+
tdi = to_timedelta([1.5, 2.25], unit="D")
124126
expected = TimedeltaIndex([Timedelta(days=1.5), Timedelta(days=2.25)])
125127
tm.assert_index_equal(tdi, expected)
126128

@@ -133,6 +135,9 @@ def test_construction_base_constructor(self):
133135
tm.assert_index_equal(pd.Index(arr), TimedeltaIndex(arr))
134136
tm.assert_index_equal(pd.Index(np.array(arr)), TimedeltaIndex(np.array(arr)))
135137

138+
@pytest.mark.filterwarnings(
139+
"ignore:The 'unit' keyword in TimedeltaIndex construction:FutureWarning"
140+
)
136141
def test_constructor(self):
137142
expected = TimedeltaIndex(
138143
[
@@ -157,15 +162,18 @@ def test_constructor(self):
157162
expected = TimedeltaIndex(
158163
["0 days 00:00:00", "0 days 00:00:01", "0 days 00:00:02"]
159164
)
160-
tm.assert_index_equal(TimedeltaIndex(range(3), unit="s"), expected)
165+
result = TimedeltaIndex(range(3), unit="s")
166+
tm.assert_index_equal(result, expected)
161167
expected = TimedeltaIndex(
162168
["0 days 00:00:00", "0 days 00:00:05", "0 days 00:00:09"]
163169
)
164-
tm.assert_index_equal(TimedeltaIndex([0, 5, 9], unit="s"), expected)
170+
result = TimedeltaIndex([0, 5, 9], unit="s")
171+
tm.assert_index_equal(result, expected)
165172
expected = TimedeltaIndex(
166173
["0 days 00:00:00.400", "0 days 00:00:00.450", "0 days 00:00:01.200"]
167174
)
168-
tm.assert_index_equal(TimedeltaIndex([400, 450, 1200], unit="ms"), expected)
175+
result = TimedeltaIndex([400, 450, 1200], unit="ms")
176+
tm.assert_index_equal(result, expected)
169177

170178
def test_constructor_iso(self):
171179
# GH #21877

pandas/tests/indexes/timedeltas/test_scalar_compat.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def test_round(self):
100100
t1 = timedelta_range("1 days", periods=3, freq="1 min 2 s 3 us")
101101
t2 = -1 * t1
102102
t1a = timedelta_range("1 days", periods=3, freq="1 min 2 s")
103-
t1c = TimedeltaIndex([1, 1, 1], unit="D")
103+
t1c = TimedeltaIndex(np.array([1, 1, 1], "m8[D]")).as_unit("ns")
104104

105105
# note that negative times round DOWN! so don't give whole numbers
106106
for freq, s1, s2 in [
@@ -122,7 +122,7 @@ def test_round(self):
122122
),
123123
("12min", t1c, TimedeltaIndex(["-1 days", "-1 days", "-1 days"])),
124124
("h", t1c, TimedeltaIndex(["-1 days", "-1 days", "-1 days"])),
125-
("d", t1c, TimedeltaIndex([-1, -1, -1], unit="D")),
125+
("d", t1c, -1 * t1c),
126126
]:
127127
r1 = t1.round(freq)
128128
tm.assert_index_equal(r1, s1)

pandas/tests/reductions/test_stat_reductions.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ def test_period_mean(self, box, freq):
6868

6969
@pytest.mark.parametrize("box", [Series, pd.Index, TimedeltaArray])
7070
def test_td64_mean(self, box):
71-
tdi = pd.TimedeltaIndex([0, 3, -2, -7, 1, 2, -1, 3, 5, -2, 4], unit="D")
71+
m8values = np.array([0, 3, -2, -7, 1, 2, -1, 3, 5, -2, 4], "m8[D]")
72+
tdi = pd.TimedeltaIndex(m8values).as_unit("ns")
7273

7374
tdarr = tdi._data
7475
obj = box(tdarr, copy=False)

pandas/tests/resample/test_timedelta.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,12 @@ def test_resample_categorical_data_with_timedeltaindex():
9898
df = DataFrame({"Group_obj": "A"}, index=pd.to_timedelta(list(range(20)), unit="s"))
9999
df["Group"] = df["Group_obj"].astype("category")
100100
result = df.resample("10s").agg(lambda x: (x.value_counts().index[0]))
101+
exp_tdi = pd.TimedeltaIndex(np.array([0, 10], dtype="m8[s]"), freq="10s").as_unit(
102+
"ns"
103+
)
101104
expected = DataFrame(
102105
{"Group_obj": ["A", "A"], "Group": ["A", "A"]},
103-
index=pd.TimedeltaIndex([0, 10], unit="s", freq="10s"),
106+
index=exp_tdi,
104107
)
105108
expected = expected.reindex(["Group_obj", "Group"], axis=1)
106109
expected["Group"] = expected["Group_obj"].astype("category")

pandas/tests/scalar/timedelta/test_constructors.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ def test_unit_parser(self, unit, np_unit, wrapper):
144144
if (unit, np_unit) in (("u", "us"), ("U", "us"), ("n", "ns"), ("N", "ns")):
145145
warn = FutureWarning
146146
else:
147-
warn = None
147+
warn = FutureWarning
148+
msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
148149
with tm.assert_produces_warning(warn, match=msg):
149150
result = to_timedelta(wrapper(range(5)), unit=unit)
150151
tm.assert_index_equal(result, expected)

0 commit comments

Comments
 (0)