Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEPR: remove deprecated units ‘H’, ’T’, and smaller from Timedelta, TimedeltaIndex #57627

Merged
2 changes: 1 addition & 1 deletion asv_bench/benchmarks/timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def setup(self):
self.dt_ts = Series(5, rng3, dtype="datetime64[ns]")

def time_resample(self):
self.dt_ts.resample("1S").last()
self.dt_ts.resample("1s").last()


class AsOf:
Expand Down
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ Removal of prior version deprecations/changes
- Enforced deprecation of string ``A`` denoting frequency in :class:`YearEnd` and strings ``A-DEC``, ``A-JAN``, etc. denoting annual frequencies with various fiscal year ends (:issue:`57699`)
- Enforced deprecation of string ``BAS`` denoting frequency in :class:`BYearBegin` and strings ``BAS-DEC``, ``BAS-JAN``, etc. denoting annual frequencies with various fiscal year starts (:issue:`57793`)
- Enforced deprecation of string ``BA`` denoting frequency in :class:`BYearEnd` and strings ``BA-DEC``, ``BA-JAN``, etc. denoting annual frequencies with various fiscal year ends (:issue:`57793`)
- Enforced deprecation of strings ``T``, ``L``, ``U``, and ``N`` denoting frequencies in :class:`Minute`, :class:`Second`, :class:`Milli`, :class:`Micro`, :class:`Nano` (:issue:`57627`)
- Enforced deprecation of strings ``T``, ``L``, ``U``, and ``N`` denoting units in :class:`Timedelta` (:issue:`57627`)
- Enforced deprecation of the behavior of :func:`concat` when ``len(keys) != len(objs)`` would truncate to the shorter of the two. Now this raises a ``ValueError`` (:issue:`43485`)
- Enforced silent-downcasting deprecation for :ref:`all relevant methods <whatsnew_220.silent_downcasting>` (:issue:`54710`)
- In :meth:`DataFrame.stack`, the default value of ``future_stack`` is now ``True``; specifying ``False`` will raise a ``FutureWarning`` (:issue:`55448`)
Expand Down
14 changes: 5 additions & 9 deletions pandas/_libs/tslibs/dtypes.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,7 @@ cdef dict c_DEPR_ABBREVS = {
"H": "h",
"BH": "bh",
"CBH": "cbh",
"T": "min",
"t": "min",
"S": "s",
"L": "ms",
"l": "ms",
"U": "us",
"u": "us",
"N": "ns",
"n": "ns",
}


Expand Down Expand Up @@ -415,13 +407,17 @@ class Resolution(Enum):
"""
cdef:
str abbrev
if freq in {"T", "t", "L", "l", "U", "u", "N", "n"}:
raise ValueError(
f"Frequency \'{freq}\' is no longer supported."
)
try:
if freq in c_DEPR_ABBREVS:
abbrev = c_DEPR_ABBREVS[freq]
warnings.warn(
f"\'{freq}\' is deprecated and will be removed in a future "
f"version. Please use \'{abbrev}\' "
"instead of \'{freq}\'.",
f"instead of \'{freq}\'.",
FutureWarning,
stacklevel=find_stack_level(),
)
Expand Down
13 changes: 6 additions & 7 deletions pandas/core/tools/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,17 @@ def to_timedelta(
* 'W'
* 'D' / 'days' / 'day'
* 'hours' / 'hour' / 'hr' / 'h' / 'H'
* 'm' / 'minute' / 'min' / 'minutes' / 'T'
* 'm' / 'minute' / 'min' / 'minutes'
* 's' / 'seconds' / 'sec' / 'second' / 'S'
* 'ms' / 'milliseconds' / 'millisecond' / 'milli' / 'millis' / 'L'
* 'us' / 'microseconds' / 'microsecond' / 'micro' / 'micros' / 'U'
* 'ns' / 'nanoseconds' / 'nano' / 'nanos' / 'nanosecond' / 'N'
* 'ms' / 'milliseconds' / 'millisecond' / 'milli' / 'millis'
* 'us' / 'microseconds' / 'microsecond' / 'micro' / 'micros'
* 'ns' / 'nanoseconds' / 'nano' / 'nanos' / 'nanosecond'

Must not be specified when `arg` contains strings and ``errors="raise"``.

.. deprecated:: 2.2.0
Units 'H', 'T', 'S', 'L', 'U' and 'N' are deprecated and will be removed
in a future version. Please use 'h', 'min', 's', 'ms', 'us', and 'ns'
instead of 'H', 'T', 'S', 'L', 'U' and 'N'.
Units 'H'and 'S' are deprecated and will be removed
in a future version. Please use 'h' and 's'.

errors : {'raise', 'coerce'}, default 'raise'
- If 'raise', then invalid parsing will raise an exception.
Expand Down
29 changes: 5 additions & 24 deletions pandas/tests/indexes/datetimes/test_date_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,30 +772,11 @@ def test_freq_dateoffset_with_relateivedelta_nanos(self):
)
tm.assert_index_equal(result, expected)

@pytest.mark.parametrize(
"freq,freq_depr",
[
("h", "H"),
("2min", "2T"),
("1s", "1S"),
("2ms", "2L"),
("1us", "1U"),
("2ns", "2N"),
],
)
def test_frequencies_H_T_S_L_U_N_deprecated(self, freq, freq_depr):
# GH#52536
freq_msg = re.split("[0-9]*", freq, maxsplit=1)[1]
freq_depr_msg = re.split("[0-9]*", freq_depr, maxsplit=1)[1]
msg = (
f"'{freq_depr_msg}' is deprecated and will be removed in a future version, "
)
f"please use '{freq_msg}' instead"

expected = date_range("1/1/2000", periods=2, freq=freq)
with tm.assert_produces_warning(FutureWarning, match=msg):
result = date_range("1/1/2000", periods=2, freq=freq_depr)
tm.assert_index_equal(result, expected)
@pytest.mark.parametrize("freq", ["2T", "2L", "1l", "1U", "2N", "2n"])
def test_frequency_H_T_S_L_U_N_raises(self, freq):
msg = f"Invalid frequency: {freq}"
with pytest.raises(ValueError, match=msg):
date_range("1/1/2000", periods=2, freq=freq)

@pytest.mark.parametrize(
"freq,freq_depr",
Expand Down
10 changes: 10 additions & 0 deletions pandas/tests/indexes/period/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ def test_period_index_from_datetime_index_invalid_freq(self, freq):
with pytest.raises(ValueError, match=msg):
rng.to_period()

@pytest.mark.parametrize("freq_depr", ["2T", "1l", "2U", "n"])
def test_period_index_T_L_U_N_raises(self, freq_depr):
# GH#9586
msg = f"Invalid frequency: {freq_depr}"

with pytest.raises(ValueError, match=msg):
period_range("2020-01", "2020-05", freq=freq_depr)
with pytest.raises(ValueError, match=msg):
PeriodIndex(["2020-01", "2020-05"], freq=freq_depr)


class TestPeriodIndex:
def test_from_ordinals(self):
Expand Down
71 changes: 38 additions & 33 deletions pandas/tests/indexes/timedeltas/test_timedelta_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,24 @@ def test_timedelta_range(self):
result = timedelta_range("0 days", freq="30min", periods=50)
tm.assert_index_equal(result, expected)

@pytest.mark.parametrize(
"depr_unit, unit",
[
("H", "hour"),
("T", "minute"),
("t", "minute"),
("S", "second"),
("L", "millisecond"),
("l", "millisecond"),
("U", "microsecond"),
("u", "microsecond"),
("N", "nanosecond"),
("n", "nanosecond"),
],
)
def test_timedelta_units_H_T_S_L_U_N_deprecated(self, depr_unit, unit):
@pytest.mark.parametrize("depr_unit, unit", [("H", "hour"), ("S", "second")])
def test_timedelta_units_H_S_deprecated(self, depr_unit, unit):
# GH#52536
depr_msg = (
f"'{depr_unit}' is deprecated and will be removed in a future version."
)

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("unit", ["T", "t", "L", "l", "U", "u", "N", "n"])
def test_timedelta_unit_T_L_U_N_raises(self, unit):
msg = f"invalid unit abbreviation: {unit}"

with pytest.raises(ValueError, match=msg):
to_timedelta(np.arange(5), unit=unit)

@pytest.mark.parametrize(
"periods, freq", [(3, "2D"), (5, "D"), (6, "19h12min"), (7, "16h"), (9, "12h")]
)
Expand All @@ -78,16 +70,21 @@ def test_linspace_behavior(self, periods, freq):
expected = timedelta_range(start="0 days", end="4 days", freq=freq)
tm.assert_index_equal(result, expected)

@pytest.mark.parametrize("msg_freq, freq", [("H", "19H12min"), ("T", "19h12T")])
def test_timedelta_range_H_T_deprecated(self, freq, msg_freq):
def test_timedelta_range_H_deprecated(self):
# GH#52536
msg = f"'{msg_freq}' is deprecated and will be removed in a future version."
msg = "'H' is deprecated and will be removed in a future version."

result = timedelta_range(start="0 days", end="4 days", periods=6)
with tm.assert_produces_warning(FutureWarning, match=msg):
expected = timedelta_range(start="0 days", end="4 days", freq=freq)
expected = timedelta_range(start="0 days", end="4 days", freq="19H12min")
tm.assert_index_equal(result, expected)

def test_timedelta_range_T_raises(self):
msg = "Invalid frequency: T"

with pytest.raises(ValueError, match=msg):
timedelta_range(start="0 days", end="4 days", freq="19h12T")

def test_errors(self):
# not enough params
msg = (
Expand Down Expand Up @@ -143,18 +140,6 @@ def test_timedelta_range_infer_freq(self):
["0 days 05:03:01", "0 days 05:03:04.500000", "0 days 05:03:08"],
"3500ms",
),
(
"2.5T",
"5 hours",
"5 hours 8 minutes",
[
"0 days 05:00:00",
"0 days 05:02:30",
"0 days 05:05:00",
"0 days 05:07:30",
],
"150s",
),
],
)
def test_timedelta_range_deprecated_freq(
Expand All @@ -171,3 +156,23 @@ def test_timedelta_range_deprecated_freq(
expected_values, dtype="timedelta64[ns]", freq=expected_freq
)
tm.assert_index_equal(result, expected)

@pytest.mark.parametrize(
"freq_depr, start, end",
[
(
"3.5l",
"05:03:01",
"05:03:10",
),
(
"2.5T",
"5 hours",
"5 hours 8 minutes",
),
],
)
def test_timedelta_range_removed_freq(self, freq_depr, start, end):
msg = f"Invalid frequency: {freq_depr}"
with pytest.raises(ValueError, match=msg):
timedelta_range(start=start, end=end, freq=freq_depr)
20 changes: 9 additions & 11 deletions pandas/tests/resample/test_period_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,22 +982,20 @@ def test_sum_min_count(self):

def test_resample_t_l_deprecated(self):
# GH#52536
msg_t = "'T' is deprecated and will be removed in a future version."
msg_l = "'L' is deprecated and will be removed in a future version."
msg_t = "Invalid frequency: T"
msg_l = "Invalid frequency: L"

with tm.assert_produces_warning(FutureWarning, match=msg_l):
rng_l = period_range(
with pytest.raises(ValueError, match=msg_l):
period_range(
"2020-01-01 00:00:00 00:00", "2020-01-01 00:00:00 00:01", freq="L"
)
rng_l = period_range(
"2020-01-01 00:00:00 00:00", "2020-01-01 00:00:00 00:01", freq="ms"
)
ser = Series(np.arange(len(rng_l)), index=rng_l)

rng = period_range(
"2020-01-01 00:00:00 00:00", "2020-01-01 00:00:00 00:01", freq="min"
)
expected = Series([29999.5, 60000.0], index=rng)
with tm.assert_produces_warning(FutureWarning, match=msg_t):
result = ser.resample("T").mean()
tm.assert_series_equal(result, expected)
with pytest.raises(ValueError, match=msg_t):
ser.resample("T").mean()

@pytest.mark.parametrize(
"freq, freq_depr, freq_res, freq_depr_res, data",
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/scalar/period/test_asfreq.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ def test_conv_annual(self):
assert ival_A.asfreq("H", "E") == ival_A_to_H_end
assert ival_A.asfreq("min", "s") == ival_A_to_T_start
assert ival_A.asfreq("min", "E") == ival_A_to_T_end
msg = "'T' is deprecated and will be removed in a future version."
with tm.assert_produces_warning(FutureWarning, match=msg):
msg = "Invalid frequency: T"
with pytest.raises(ValueError, match=msg):
assert ival_A.asfreq("T", "s") == ival_A_to_T_start
assert ival_A.asfreq("T", "E") == ival_A_to_T_end
msg = "'S' is deprecated and will be removed in a future version."
Expand Down
45 changes: 19 additions & 26 deletions pandas/tests/scalar/timedelta/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,14 @@ def test_unit_m_y_raises(self, unit):
with pytest.raises(ValueError, match=msg):
to_timedelta([1, 2], unit)

@pytest.mark.parametrize(
"unit,unit_depr",
[
("h", "H"),
("min", "T"),
("s", "S"),
("ms", "L"),
("ns", "N"),
("us", "U"),
],
)
def test_units_H_T_S_L_N_U_deprecated(self, unit, unit_depr):
@pytest.mark.parametrize("unit", ["h", "s"])
def test_units_H_S_deprecated(self, unit):
# GH#52536
msg = f"'{unit_depr}' is deprecated and will be removed in a future version."
msg = f"'{unit.upper()}' is deprecated and will be removed in a future version."

expected = Timedelta(1, unit=unit)
with tm.assert_produces_warning(FutureWarning, match=msg):
result = Timedelta(1, unit=unit_depr)
result = Timedelta(1, unit=unit.upper())
tm.assert_equal(result, expected)

@pytest.mark.parametrize(
Expand Down Expand Up @@ -103,13 +93,11 @@ def test_units_H_T_S_L_N_U_deprecated(self, unit, unit_depr):
"microsecond",
"micro",
"micros",
"u",
"US",
"Microseconds",
"Microsecond",
"Micro",
"Micros",
"U",
]
]
+ [
Expand All @@ -120,13 +108,11 @@ def test_units_H_T_S_L_N_U_deprecated(self, unit, unit_depr):
"nanosecond",
"nano",
"nanos",
"n",
"NS",
"Nanoseconds",
"Nanosecond",
"Nano",
"Nanos",
"N",
]
],
)
Expand All @@ -139,14 +125,9 @@ def test_unit_parser(self, unit, np_unit, wrapper):
dtype="m8[ns]",
)
# TODO(2.0): the desired output dtype may have non-nano resolution
msg = f"'{unit}' is deprecated and will be removed in a future version."

if (unit, np_unit) in (("u", "us"), ("U", "us"), ("n", "ns"), ("N", "ns")):
warn = FutureWarning
else:
warn = FutureWarning
msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
with tm.assert_produces_warning(warn, match=msg):

msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
result = to_timedelta(wrapper(range(5)), unit=unit)
tm.assert_index_equal(result, expected)
result = TimedeltaIndex(wrapper(range(5)), unit=unit)
Expand All @@ -170,6 +151,18 @@ def test_unit_parser(self, unit, np_unit, wrapper):
result = Timedelta(f"2{unit}")
assert result == expected

@pytest.mark.parametrize("unit", ["T", "t", "L", "l", "U", "u", "N", "n"])
def test_unit_T_L_N_U_raises(self, unit):
msg = f"invalid unit abbreviation: {unit}"
with pytest.raises(ValueError, match=msg):
Timedelta(1, unit=unit)

with pytest.raises(ValueError, match=msg):
to_timedelta(10, unit)

with pytest.raises(ValueError, match=msg):
to_timedelta([1, 2], unit)


def test_construct_from_kwargs_overflow():
# GH#55503
Expand Down
11 changes: 9 additions & 2 deletions pandas/tests/tslibs/test_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,17 @@ def test_get_attrname_from_abbrev(freqstr, expected):
assert reso.attrname == expected


@pytest.mark.parametrize("freq", ["H", "T", "S", "L", "U", "N"])
def test_units_H_T_S_L_U_N_deprecated_from_attrname_to_abbrevs(freq):
@pytest.mark.parametrize("freq", ["H", "S"])
def test_units_H_S_deprecated_from_attrname_to_abbrevs(freq):
# GH#52536
msg = f"'{freq}' is deprecated and will be removed in a future version."

with tm.assert_produces_warning(FutureWarning, match=msg):
Resolution.get_reso_from_freqstr(freq)


@pytest.mark.parametrize("freq", ["T", "t", "L", "U", "N", "n"])
def test_reso_abbrev_T_L_U_N_raises(freq):
msg = f"Frequency '{freq}' is no longer supported."
with pytest.raises(ValueError, match=msg):
Resolution.get_reso_from_freqstr(freq)