diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index d9cdc8beaebea..5fd6953d0443a 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -295,10 +295,10 @@ Deprecations - Deprecated option "mode.use_inf_as_na", convert inf entries to ``NaN`` before instead (:issue:`51684`) - Deprecated parameter ``obj`` in :meth:`GroupBy.get_group` (:issue:`53545`) - Deprecated positional indexing on :class:`Series` with :meth:`Series.__getitem__` and :meth:`Series.__setitem__`, in a future version ``ser[item]`` will *always* interpret ``item`` as a label, not a position (:issue:`50617`) +- Deprecated strings ``T``, ``t``, ``L`` and ``l`` denoting units in :func:`to_timedelta` (:issue:`52536`) - Deprecated the "method" and "limit" keywords on :meth:`Series.fillna`, :meth:`DataFrame.fillna`, :meth:`SeriesGroupBy.fillna`, :meth:`DataFrameGroupBy.fillna`, and :meth:`Resampler.fillna`, use ``obj.bfill()`` or ``obj.ffill()`` instead (:issue:`53394`) - Deprecated the ``method`` and ``limit`` keywords in :meth:`DataFrame.replace` and :meth:`Series.replace` (:issue:`33302`) - Deprecated values "pad", "ffill", "bfill", "backfill" for :meth:`Series.interpolate` and :meth:`DataFrame.interpolate`, use ``obj.ffill()`` or ``obj.bfill()`` instead (:issue:`53581`) -- .. --------------------------------------------------------------------------- .. _whatsnew_210.performance: diff --git a/pandas/_libs/tslibs/timedeltas.pyi b/pandas/_libs/tslibs/timedeltas.pyi index 0d5afbfe963f1..448aed0eebe4c 100644 --- a/pandas/_libs/tslibs/timedeltas.pyi +++ b/pandas/_libs/tslibs/timedeltas.pyi @@ -37,6 +37,7 @@ UnitChoices = Literal[ "minute", "min", "minutes", + "T", "t", "s", "seconds", @@ -47,6 +48,7 @@ UnitChoices = Literal[ "millisecond", "milli", "millis", + "L", "l", "us", "microseconds", diff --git a/pandas/core/tools/timedeltas.py b/pandas/core/tools/timedeltas.py index ad366e58c2f06..95946f0a159fd 100644 --- a/pandas/core/tools/timedeltas.py +++ b/pandas/core/tools/timedeltas.py @@ -7,6 +7,7 @@ TYPE_CHECKING, overload, ) +import warnings import numpy as np @@ -19,6 +20,7 @@ Timedelta, parse_timedelta_unit, ) +from pandas.util._exceptions import find_stack_level from pandas.core.dtypes.common import is_list_like from pandas.core.dtypes.generic import ( @@ -118,6 +120,9 @@ def to_timedelta( Must not be specified when `arg` context strings and ``errors="raise"``. + .. deprecated:: 2.1.0 + Units 'T' and 'L' are deprecated and will be removed in a future version. + errors : {'ignore', 'raise', 'coerce'}, default 'raise' - If 'raise', then invalid parsing will raise an exception. - If 'coerce', then invalid parsing will be set as NaT. @@ -169,6 +174,13 @@ def to_timedelta( TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'], dtype='timedelta64[ns]', freq=None) """ + if unit in {"T", "t", "L", "l"}: + warnings.warn( + f"Unit '{unit}' is deprecated and will be removed in a future version.", + FutureWarning, + stacklevel=find_stack_level(), + ) + if unit is not None: unit = parse_timedelta_unit(unit) diff --git a/pandas/tests/indexes/timedeltas/test_timedelta_range.py b/pandas/tests/indexes/timedeltas/test_timedelta_range.py index 05fdddd7a4f4f..72bdc6da47d94 100644 --- a/pandas/tests/indexes/timedeltas/test_timedelta_range.py +++ b/pandas/tests/indexes/timedeltas/test_timedelta_range.py @@ -38,10 +38,27 @@ def test_timedelta_range(self): result = timedelta_range("1 days, 00:00:02", periods=5, freq="2D") tm.assert_index_equal(result, expected) - expected = to_timedelta(np.arange(50), unit="T") * 30 - result = timedelta_range("0 days", freq="30T", periods=50) + expected = to_timedelta(np.arange(50), unit="min") * 30 + result = timedelta_range("0 days", freq="30min", periods=50) tm.assert_index_equal(result, expected) + @pytest.mark.parametrize( + "depr_unit, unit", + [ + ("T", "minute"), + ("t", "minute"), + ("L", "millisecond"), + ("l", "millisecond"), + ], + ) + def test_timedelta_units_T_L_deprecated(self, depr_unit, unit): + depr_msg = f"Unit '{depr_unit}' is deprecated." + + expected = to_timedelta(np.arange(5), unit=unit) + with tm.assert_produces_warning(FutureWarning, match=depr_msg): + result = to_timedelta(np.arange(5), unit=depr_unit) + tm.assert_index_equal(result, expected) + @pytest.mark.parametrize( "periods, freq", [(3, "2D"), (5, "D"), (6, "19H12T"), (7, "16H"), (9, "12H")] ) diff --git a/pandas/tests/resample/test_timedelta.py b/pandas/tests/resample/test_timedelta.py index 79e024ef84c90..d87e6ca2f69b9 100644 --- a/pandas/tests/resample/test_timedelta.py +++ b/pandas/tests/resample/test_timedelta.py @@ -48,17 +48,17 @@ def test_resample_as_freq_with_subperiod(): def test_resample_with_timedeltas(): expected = DataFrame({"A": np.arange(1480)}) expected = expected.groupby(expected.index // 30).sum() - expected.index = timedelta_range("0 days", freq="30T", periods=50) + expected.index = timedelta_range("0 days", freq="30min", periods=50) df = DataFrame( - {"A": np.arange(1480)}, index=pd.to_timedelta(np.arange(1480), unit="T") + {"A": np.arange(1480)}, index=pd.to_timedelta(np.arange(1480), unit="min") ) - result = df.resample("30T").sum() + result = df.resample("30min").sum() tm.assert_frame_equal(result, expected) s = df["A"] - result = s.resample("30T").sum() + result = s.resample("30min").sum() tm.assert_series_equal(result, expected["A"]) diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 4cb77b2f1d065..722a68a1dce71 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -492,11 +492,9 @@ def test_nat_converters(self): "minute", "min", "minutes", - "t", "Minute", "Min", "Minutes", - "T", ] ] + [ @@ -520,13 +518,11 @@ def test_nat_converters(self): "millisecond", "milli", "millis", - "l", "MS", "Milliseconds", "Millisecond", "Milli", "Millis", - "L", ] ] + [