Skip to content

Commit 7e0d36f

Browse files
authored
DEPR offsets: rename ‘Y’ to ‘YE' (#55792)
1 parent 95561fc commit 7e0d36f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+237
-169
lines changed

doc/source/user_guide/timeseries.rst

+15-15
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ into ``freq`` keyword arguments. The available date offsets and associated frequ
889889
:class:`~pandas.tseries.offsets.BQuarterEnd`, ``'BQ``, "business quarter end"
890890
:class:`~pandas.tseries.offsets.BQuarterBegin`, ``'BQS'``, "business quarter begin"
891891
:class:`~pandas.tseries.offsets.FY5253Quarter`, ``'REQ'``, "retail (aka 52-53 week) quarter"
892-
:class:`~pandas.tseries.offsets.YearEnd`, ``'Y'``, "calendar year end"
892+
:class:`~pandas.tseries.offsets.YearEnd`, ``'YE'``, "calendar year end"
893893
:class:`~pandas.tseries.offsets.YearBegin`, ``'YS'`` or ``'BYS'``,"calendar year begin"
894894
:class:`~pandas.tseries.offsets.BYearEnd`, ``'BY'``, "business year end"
895895
:class:`~pandas.tseries.offsets.BYearBegin`, ``'BYS'``, "business year begin"
@@ -1252,7 +1252,7 @@ frequencies. We will refer to these aliases as *offset aliases*.
12521252
"BQ", "business quarter end frequency"
12531253
"QS", "quarter start frequency"
12541254
"BQS", "business quarter start frequency"
1255-
"Y", "year end frequency"
1255+
"YE", "year end frequency"
12561256
"BY", "business year end frequency"
12571257
"YS", "year start frequency"
12581258
"BYS", "business year start frequency"
@@ -1379,18 +1379,18 @@ For some frequencies you can specify an anchoring suffix:
13791379
"(B)Q(E)(S)\-SEP", "quarterly frequency, year ends in September"
13801380
"(B)Q(E)(S)\-OCT", "quarterly frequency, year ends in October"
13811381
"(B)Q(E)(S)\-NOV", "quarterly frequency, year ends in November"
1382-
"(B)Y(S)\-DEC", "annual frequency, anchored end of December. Same as 'Y'"
1383-
"(B)Y(S)\-JAN", "annual frequency, anchored end of January"
1384-
"(B)Y(S)\-FEB", "annual frequency, anchored end of February"
1385-
"(B)Y(S)\-MAR", "annual frequency, anchored end of March"
1386-
"(B)Y(S)\-APR", "annual frequency, anchored end of April"
1387-
"(B)Y(S)\-MAY", "annual frequency, anchored end of May"
1388-
"(B)Y(S)\-JUN", "annual frequency, anchored end of June"
1389-
"(B)Y(S)\-JUL", "annual frequency, anchored end of July"
1390-
"(B)Y(S)\-AUG", "annual frequency, anchored end of August"
1391-
"(B)Y(S)\-SEP", "annual frequency, anchored end of September"
1392-
"(B)Y(S)\-OCT", "annual frequency, anchored end of October"
1393-
"(B)Y(S)\-NOV", "annual frequency, anchored end of November"
1382+
"(B)Y(E)(S)\-DEC", "annual frequency, anchored end of December. Same as 'YE'"
1383+
"(B)Y(E)(S)\-JAN", "annual frequency, anchored end of January"
1384+
"(B)Y(E)(S)\-FEB", "annual frequency, anchored end of February"
1385+
"(B)Y(E)(S)\-MAR", "annual frequency, anchored end of March"
1386+
"(B)Y(E)(S)\-APR", "annual frequency, anchored end of April"
1387+
"(B)Y(E)(S)\-MAY", "annual frequency, anchored end of May"
1388+
"(B)Y(E)(S)\-JUN", "annual frequency, anchored end of June"
1389+
"(B)Y(E)(S)\-JUL", "annual frequency, anchored end of July"
1390+
"(B)Y(E)(S)\-AUG", "annual frequency, anchored end of August"
1391+
"(B)Y(E)(S)\-SEP", "annual frequency, anchored end of September"
1392+
"(B)Y(E)(S)\-OCT", "annual frequency, anchored end of October"
1393+
"(B)Y(E)(S)\-NOV", "annual frequency, anchored end of November"
13941394

13951395
These can be used as arguments to ``date_range``, ``bdate_range``, constructors
13961396
for ``DatetimeIndex``, as well as various other timeseries-related functions
@@ -1686,7 +1686,7 @@ the end of the interval.
16861686
.. warning::
16871687

16881688
The default values for ``label`` and ``closed`` is '**left**' for all
1689-
frequency offsets except for 'ME', 'Y', 'QE', 'BME', 'BY', 'BQ', and 'W'
1689+
frequency offsets except for 'ME', 'YE', 'QE', 'BME', 'BY', 'BQ', and 'W'
16901690
which all have a default of 'right'.
16911691

16921692
This might unintendedly lead to looking ahead, where the value for a later

doc/source/whatsnew/v2.2.0.rst

+6-21
Original file line numberDiff line numberDiff line change
@@ -232,29 +232,14 @@ Other API changes
232232
Deprecations
233233
~~~~~~~~~~~~
234234

235-
Deprecate aliases ``M`` and ``Q`` in favour of ``ME`` and ``QE`` for offsets
236-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
235+
Deprecate aliases ``M``, ``Q``, and ``Y`` in favour of ``ME``, ``QE``, and ``YE`` for offsets
236+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
237237

238-
The alias ``M`` is deprecated in favour of ``ME`` for offsets, please use ``ME`` for "month end" instead of ``M`` (:issue:`9586`)
238+
Deprecated the following frequency aliases (:issue:`9586`):
239239

240-
For example:
241-
242-
*Previous behavior*:
243-
244-
.. code-block:: ipython
245-
246-
In [7]: pd.date_range('2020-01-01', periods=3, freq='M')
247-
Out [7]:
248-
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31'],
249-
dtype='datetime64[ns]', freq='M')
250-
251-
*Future behavior*:
252-
253-
.. ipython:: python
254-
255-
pd.date_range('2020-01-01', periods=3, freq='ME')
256-
257-
The alias ``Q`` is deprecated in favour of ``QE`` for offsets, please use ``QE`` for "quarter end" instead of ``Q`` (:issue:`9586`)
240+
- ``M`` (month end) has been renamed ``ME`` for offsets
241+
- ``Q`` (quarter end) has been renamed ``QE`` for offsets
242+
- ``Y`` (year end) has been renamed ``YE`` for offsets
258243

259244
For example:
260245

pandas/_libs/tslibs/dtypes.pyx

+39
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,19 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
214214
"QE-SEP": "Q-SEP",
215215
"QE-OCT": "Q-OCT",
216216
"QE-NOV": "Q-NOV",
217+
"YE": "Y",
218+
"YE-DEC": "Y-DEC",
219+
"YE-JAN": "Y-JAN",
220+
"YE-FEB": "Y-FEB",
221+
"YE-MAR": "Y-MAR",
222+
"YE-APR": "Y-APR",
223+
"YE-MAY": "Y-MAY",
224+
"YE-JUN": "Y-JUN",
225+
"YE-JUL": "Y-JUL",
226+
"YE-AUG": "Y-AUG",
227+
"YE-SEP": "Y-SEP",
228+
"YE-OCT": "Y-OCT",
229+
"YE-NOV": "Y-NOV",
217230
"W": "W",
218231
"ME": "M",
219232
"Y": "Y",
@@ -236,6 +249,32 @@ OFFSET_DEPR_FREQSTR: dict[str, str]= {
236249
"Q-SEP": "QE-SEP",
237250
"Q-OCT": "QE-OCT",
238251
"Q-NOV": "QE-NOV",
252+
"Y": "YE",
253+
"Y-DEC": "YE-DEC",
254+
"Y-JAN": "YE-JAN",
255+
"Y-FEB": "YE-FEB",
256+
"Y-MAR": "YE-MAR",
257+
"Y-APR": "YE-APR",
258+
"Y-MAY": "YE-MAY",
259+
"Y-JUN": "YE-JUN",
260+
"Y-JUL": "YE-JUL",
261+
"Y-AUG": "YE-AUG",
262+
"Y-SEP": "YE-SEP",
263+
"Y-OCT": "YE-OCT",
264+
"Y-NOV": "YE-NOV",
265+
"A": "YE",
266+
"A-DEC": "YE-DEC",
267+
"A-JAN": "YE-JAN",
268+
"A-FEB": "YE-FEB",
269+
"A-MAR": "YE-MAR",
270+
"A-APR": "YE-APR",
271+
"A-MAY": "YE-MAY",
272+
"A-JUN": "YE-JUN",
273+
"A-JUL": "YE-JUL",
274+
"A-AUG": "YE-AUG",
275+
"A-SEP": "YE-SEP",
276+
"A-OCT": "YE-OCT",
277+
"A-NOV": "YE-NOV",
239278
}
240279
cdef dict c_OFFSET_TO_PERIOD_FREQSTR = OFFSET_TO_PERIOD_FREQSTR
241280
cdef dict c_OFFSET_DEPR_FREQSTR = OFFSET_DEPR_FREQSTR

pandas/_libs/tslibs/offsets.pyx

+12-3
Original file line numberDiff line numberDiff line change
@@ -2518,7 +2518,7 @@ cdef class YearEnd(YearOffset):
25182518
"""
25192519

25202520
_default_month = 12
2521-
_prefix = "Y"
2521+
_prefix = "YE"
25222522
_day_opt = "end"
25232523

25242524
cdef readonly:
@@ -4562,7 +4562,7 @@ prefix_mapping = {
45624562
offset._prefix: offset
45634563
for offset in [
45644564
YearBegin, # 'YS'
4565-
YearEnd, # 'Y'
4565+
YearEnd, # 'YE'
45664566
BYearBegin, # 'BYS'
45674567
BYearEnd, # 'BY'
45684568
BusinessDay, # 'B'
@@ -4604,7 +4604,7 @@ _lite_rule_alias = {
46044604
"W": "W-SUN",
46054605
"QE": "QE-DEC",
46064606

4607-
"Y": "Y-DEC", # YearEnd(month=12),
4607+
"YE": "YE-DEC", # YearEnd(month=12),
46084608
"YS": "YS-JAN", # YearBegin(month=1),
46094609
"BY": "BY-DEC", # BYearEnd(month=12),
46104610
"BYS": "BYS-JAN", # BYearBegin(month=1),
@@ -4637,6 +4637,7 @@ _dont_uppercase = {
46374637
"qe-sep",
46384638
"qe-oct",
46394639
"qe-nov",
4640+
"ye",
46404641
}
46414642

46424643

@@ -4762,6 +4763,14 @@ cpdef to_offset(freq, bint is_period=False):
47624763
f"instead of \'{name}\'"
47634764
)
47644765
elif is_period is True and name in c_OFFSET_DEPR_FREQSTR:
4766+
if name.startswith("A"):
4767+
warnings.warn(
4768+
f"\'{name}\' is deprecated and will be removed in a future "
4769+
f"version, please use \'{c_DEPR_ABBREVS.get(name)}\' "
4770+
f"instead.",
4771+
FutureWarning,
4772+
stacklevel=find_stack_level(),
4773+
)
47654774
name = c_OFFSET_DEPR_FREQSTR.get(name)
47664775

47674776
if sep != "" and not sep.isspace():

pandas/core/arrays/datetimes.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1520,7 +1520,7 @@ def isocalendar(self) -> DataFrame:
15201520
Examples
15211521
--------
15221522
>>> datetime_series = pd.Series(
1523-
... pd.date_range("2000-01-01", periods=3, freq="Y")
1523+
... pd.date_range("2000-01-01", periods=3, freq="YE")
15241524
... )
15251525
>>> datetime_series
15261526
0 2000-12-31
@@ -2058,10 +2058,10 @@ def isocalendar(self) -> DataFrame:
20582058
This method is available on Series with datetime values under
20592059
the ``.dt`` accessor, and directly on DatetimeIndex.
20602060
2061-
>>> idx = pd.date_range("2012-01-01", "2015-01-01", freq="Y")
2061+
>>> idx = pd.date_range("2012-01-01", "2015-01-01", freq="YE")
20622062
>>> idx
20632063
DatetimeIndex(['2012-12-31', '2013-12-31', '2014-12-31'],
2064-
dtype='datetime64[ns]', freq='Y-DEC')
2064+
dtype='datetime64[ns]', freq='YE-DEC')
20652065
>>> idx.is_leap_year
20662066
array([ True, False, False])
20672067

pandas/core/generic.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -9199,11 +9199,11 @@ def resample(
91999199
Use frame.T.resample(...) instead.
92009200
closed : {{'right', 'left'}}, default None
92019201
Which side of bin interval is closed. The default is 'left'
9202-
for all frequency offsets except for 'ME', 'Y', 'Q', 'BME',
9202+
for all frequency offsets except for 'ME', 'YE', 'QE', 'BME',
92039203
'BA', 'BQ', and 'W' which all have a default of 'right'.
92049204
label : {{'right', 'left'}}, default None
92059205
Which bin edge label to label bucket with. The default is 'left'
9206-
for all frequency offsets except for 'ME', 'Y', 'Q', 'BME',
9206+
for all frequency offsets except for 'ME', 'YE', 'QE', 'BME',
92079207
'BA', 'BQ', and 'W' which all have a default of 'right'.
92089208
convention : {{'start', 'end', 's', 'e'}}, default 'start'
92099209
For `PeriodIndex` only, controls whether to use the start or

pandas/core/resample.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2130,7 +2130,7 @@ def __init__(
21302130
else:
21312131
freq = to_offset(freq)
21322132

2133-
end_types = {"ME", "Y", "QE", "BME", "BY", "BQ", "W"}
2133+
end_types = {"ME", "YE", "QE", "BME", "BY", "BQ", "W"}
21342134
rule = freq.rule_code
21352135
if rule in end_types or ("-" in rule and rule[: rule.find("-")] in end_types):
21362136
if closed is None:
@@ -2330,7 +2330,7 @@ def _adjust_bin_edges(
23302330
"BQ",
23312331
"BY",
23322332
"QE",
2333-
"Y",
2333+
"YE",
23342334
"W",
23352335
):
23362336
# If the right end-point is on the last day of the month, roll forwards

pandas/core/series.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5785,7 +5785,7 @@ def to_timestamp(
57855785
2023-01-31 1
57865786
2024-01-31 2
57875787
2025-01-31 3
5788-
Freq: Y-JAN, dtype: int64
5788+
Freq: YE-JAN, dtype: int64
57895789
"""
57905790
if not isinstance(self.index, PeriodIndex):
57915791
raise TypeError(f"unsupported Type {type(self.index).__name__}")

pandas/tests/arithmetic/test_datetime64.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ def test_dt64_series_arith_overflow(self):
16061606
# GH#12534, fixed by GH#19024
16071607
dt = Timestamp("1700-01-31")
16081608
td = Timedelta("20000 Days")
1609-
dti = date_range("1949-09-30", freq="100Y", periods=4)
1609+
dti = date_range("1949-09-30", freq="100YE", periods=4)
16101610
ser = Series(dti)
16111611
msg = "Overflow in int64 addition"
16121612
with pytest.raises(OverflowError, match=msg):

pandas/tests/arrays/period/test_arrow_compat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def test_arrow_extension_type():
3838
"data, freq",
3939
[
4040
(pd.date_range("2017", periods=3), "D"),
41-
(pd.date_range("2017", periods=3, freq="Y"), "Y-DEC"),
41+
(pd.date_range("2017", periods=3, freq="YE"), "Y-DEC"),
4242
],
4343
)
4444
def test_arrow_array(data, freq):

pandas/tests/arrays/test_datetimelike.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131

3232
# TODO: more freq variants
33-
@pytest.fixture(params=["D", "B", "W", "ME", "QE", "Y"])
33+
@pytest.fixture(params=["D", "B", "W", "ME", "QE", "YE"])
3434
def freqstr(request):
3535
"""Fixture returning parametrized frequency in string format."""
3636
return request.param

pandas/tests/arrays/test_datetimes.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -748,10 +748,14 @@ def test_iter_zoneinfo_fold(self, tz):
748748
("2ME", "2M"),
749749
("2QE", "2Q"),
750750
("2QE-SEP", "2Q-SEP"),
751+
("1YE", "1Y"),
752+
("2YE-MAR", "2Y-MAR"),
753+
("1YE", "1A"),
754+
("2YE-MAR", "2A-MAR"),
751755
],
752756
)
753-
def test_date_range_frequency_M_Q_deprecated(self, freq, freq_depr):
754-
# GH#9586
757+
def test_date_range_frequency_M_Q_Y_A_deprecated(self, freq, freq_depr):
758+
# GH#9586, GH#54275
755759
depr_msg = (
756760
f"'{freq_depr[1:]}' will be deprecated, please use '{freq[1:]}' instead."
757761
)

pandas/tests/frame/methods/test_asfreq.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,13 @@ def test_asfreq_2ME(self, freq, freq_half):
240240
("2ME", "2M"),
241241
("2QE", "2Q"),
242242
("2QE-SEP", "2Q-SEP"),
243+
("1YE", "1Y"),
244+
("2YE-MAR", "2Y-MAR"),
245+
("1YE", "1A"),
246+
("2YE-MAR", "2A-MAR"),
243247
],
244248
)
245-
def test_asfreq_frequency_M_Q_deprecated(self, freq, freq_depr):
249+
def test_asfreq_frequency_M_Q_Y_A_deprecated(self, freq, freq_depr):
246250
# GH#9586
247251
depr_msg = (
248252
f"'{freq_depr[1:]}' will be deprecated, please use '{freq[1:]}' instead."

pandas/tests/frame/methods/test_reindex.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_dti_set_index_reindex_datetimeindex(self):
3737
# GH#6631
3838
df = DataFrame(np.random.default_rng(2).random(6))
3939
idx1 = date_range("2011/01/01", periods=6, freq="ME", tz="US/Eastern")
40-
idx2 = date_range("2013", periods=6, freq="Y", tz="Asia/Tokyo")
40+
idx2 = date_range("2013", periods=6, freq="YE", tz="Asia/Tokyo")
4141

4242
df = df.set_index(idx1)
4343
tm.assert_index_equal(df.index, idx1)

pandas/tests/frame/methods/test_to_timestamp.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import pandas._testing as tm
1717

1818

19-
def _get_with_delta(delta, freq="Y-DEC"):
19+
def _get_with_delta(delta, freq="YE-DEC"):
2020
return date_range(
2121
to_datetime("1/1/2001") + delta,
2222
to_datetime("12/31/2009") + delta,
@@ -36,7 +36,7 @@ def test_to_timestamp(self, frame_or_series):
3636
obj["mix"] = "a"
3737
obj = tm.get_obj(obj, frame_or_series)
3838

39-
exp_index = date_range("1/1/2001", end="12/31/2009", freq="Y-DEC")
39+
exp_index = date_range("1/1/2001", end="12/31/2009", freq="YE-DEC")
4040
exp_index = exp_index + Timedelta(1, "D") - Timedelta(1, "ns")
4141
result = obj.to_timestamp("D", "end")
4242
tm.assert_index_equal(result.index, exp_index)
@@ -82,7 +82,7 @@ def test_to_timestamp_columns(self):
8282
# columns
8383
df = df.T
8484

85-
exp_index = date_range("1/1/2001", end="12/31/2009", freq="Y-DEC")
85+
exp_index = date_range("1/1/2001", end="12/31/2009", freq="YE-DEC")
8686
exp_index = exp_index + Timedelta(1, "D") - Timedelta(1, "ns")
8787
result = df.to_timestamp("D", "end", axis=1)
8888
tm.assert_index_equal(result.columns, exp_index)

pandas/tests/frame/test_repr.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ def test_repr_np_nat_with_object(self, arg, box, expected):
357357
assert result == expected
358358

359359
def test_frame_datetime64_pre1900_repr(self):
360-
df = DataFrame({"year": date_range("1/1/1700", periods=50, freq="Y-DEC")})
360+
df = DataFrame({"year": date_range("1/1/1700", periods=50, freq="YE-DEC")})
361361
# it works!
362362
repr(df)
363363

pandas/tests/groupby/test_timegrouper.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def test_timegrouper_with_reg_groups(self):
192192
).set_index(["Date", "Buyer"])
193193

194194
msg = "The default value of numeric_only"
195-
result = df.groupby([Grouper(freq="Y"), "Buyer"]).sum(numeric_only=True)
195+
result = df.groupby([Grouper(freq="YE"), "Buyer"]).sum(numeric_only=True)
196196
tm.assert_frame_equal(result, expected)
197197

198198
expected = DataFrame(
@@ -335,7 +335,7 @@ def test_timegrouper_with_reg_groups(self):
335335
)
336336
tm.assert_frame_equal(result, expected)
337337

338-
@pytest.mark.parametrize("freq", ["D", "ME", "Y", "QE-APR"])
338+
@pytest.mark.parametrize("freq", ["D", "ME", "YE", "QE-APR"])
339339
def test_timegrouper_with_reg_groups_freq(self, freq):
340340
# GH 6764 multiple grouping with/without sort
341341
df = DataFrame(
@@ -906,7 +906,7 @@ def test_groupby_apply_timegrouper_with_nat_apply_squeeze(
906906

907907
# We need to create a GroupBy object with only one non-NaT group,
908908
# so use a huge freq so that all non-NaT dates will be grouped together
909-
tdg = Grouper(key="Date", freq="100Y")
909+
tdg = Grouper(key="Date", freq="100YE")
910910
gb = df.groupby(tdg)
911911

912912
# check that we will go through the singular_series path

0 commit comments

Comments
 (0)