Skip to content

Commit e0a8443

Browse files
authored
DEPR offsets: rename 'Q' to 'QE' (#55553)
* add dictionary OFFSET_DEPR_FREQSTR, change warning msg * rename Q to QE for offsets * correct def _adjust_bin_edges, dicts OFFSET_DEPR_FREQSTR, OFFSET_TO_PERIOD_FREQSTR, fix tests * correct def convert_json_field_to_pandas_type * correct doc * add tests, correct user_guide/timeseries.rst * fix pylint failure * correct docstring * add a note to v2.2.0.rst * remove test_my * fix tests * roll back my changes in convert_json_field_to_pandas_type, correct v2.2.0.rst * add 'qe' to _dont_uppercase * add parameters Q, 2Q to test_read_json_table_orient_period_depr_freq * correct DatetimeProperties docs
1 parent 6ef695f commit e0a8443

30 files changed

+248
-121
lines changed

doc/source/user_guide/timeseries.rst

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ into ``freq`` keyword arguments. The available date offsets and associated frequ
890890
:class:`~pandas.tseries.offsets.CBMonthBegin` or :class:`~pandas.tseries.offsets.CustomBusinessMonthBegin`, ``'CBMS'``, "custom business month begin"
891891
:class:`~pandas.tseries.offsets.SemiMonthEnd`, ``'SM'``, "15th (or other day_of_month) and calendar month end"
892892
:class:`~pandas.tseries.offsets.SemiMonthBegin`, ``'SMS'``, "15th (or other day_of_month) and calendar month begin"
893-
:class:`~pandas.tseries.offsets.QuarterEnd`, ``'Q'``, "calendar quarter end"
893+
:class:`~pandas.tseries.offsets.QuarterEnd`, ``'QE'``, "calendar quarter end"
894894
:class:`~pandas.tseries.offsets.QuarterBegin`, ``'QS'``, "calendar quarter begin"
895895
:class:`~pandas.tseries.offsets.BQuarterEnd`, ``'BQ``, "business quarter end"
896896
:class:`~pandas.tseries.offsets.BQuarterBegin`, ``'BQS'``, "business quarter begin"
@@ -1254,7 +1254,7 @@ frequencies. We will refer to these aliases as *offset aliases*.
12541254
"SMS", "semi-month start frequency (1st and 15th)"
12551255
"BMS", "business month start frequency"
12561256
"CBMS", "custom business month start frequency"
1257-
"Q", "quarter end frequency"
1257+
"QE", "quarter end frequency"
12581258
"BQ", "business quarter end frequency"
12591259
"QS", "quarter start frequency"
12601260
"BQS", "business quarter start frequency"
@@ -1373,18 +1373,18 @@ For some frequencies you can specify an anchoring suffix:
13731373
"W\-THU", "weekly frequency (Thursdays)"
13741374
"W\-FRI", "weekly frequency (Fridays)"
13751375
"W\-SAT", "weekly frequency (Saturdays)"
1376-
"(B)Q(S)\-DEC", "quarterly frequency, year ends in December. Same as 'Q'"
1377-
"(B)Q(S)\-JAN", "quarterly frequency, year ends in January"
1378-
"(B)Q(S)\-FEB", "quarterly frequency, year ends in February"
1379-
"(B)Q(S)\-MAR", "quarterly frequency, year ends in March"
1380-
"(B)Q(S)\-APR", "quarterly frequency, year ends in April"
1381-
"(B)Q(S)\-MAY", "quarterly frequency, year ends in May"
1382-
"(B)Q(S)\-JUN", "quarterly frequency, year ends in June"
1383-
"(B)Q(S)\-JUL", "quarterly frequency, year ends in July"
1384-
"(B)Q(S)\-AUG", "quarterly frequency, year ends in August"
1385-
"(B)Q(S)\-SEP", "quarterly frequency, year ends in September"
1386-
"(B)Q(S)\-OCT", "quarterly frequency, year ends in October"
1387-
"(B)Q(S)\-NOV", "quarterly frequency, year ends in November"
1376+
"(B)Q(E)(S)\-DEC", "quarterly frequency, year ends in December. Same as 'QE'"
1377+
"(B)Q(E)(S)\-JAN", "quarterly frequency, year ends in January"
1378+
"(B)Q(E)(S)\-FEB", "quarterly frequency, year ends in February"
1379+
"(B)Q(E)(S)\-MAR", "quarterly frequency, year ends in March"
1380+
"(B)Q(E)(S)\-APR", "quarterly frequency, year ends in April"
1381+
"(B)Q(E)(S)\-MAY", "quarterly frequency, year ends in May"
1382+
"(B)Q(E)(S)\-JUN", "quarterly frequency, year ends in June"
1383+
"(B)Q(E)(S)\-JUL", "quarterly frequency, year ends in July"
1384+
"(B)Q(E)(S)\-AUG", "quarterly frequency, year ends in August"
1385+
"(B)Q(E)(S)\-SEP", "quarterly frequency, year ends in September"
1386+
"(B)Q(E)(S)\-OCT", "quarterly frequency, year ends in October"
1387+
"(B)Q(E)(S)\-NOV", "quarterly frequency, year ends in November"
13881388
"(B)Y(S)\-DEC", "annual frequency, anchored end of December. Same as 'Y'"
13891389
"(B)Y(S)\-JAN", "annual frequency, anchored end of January"
13901390
"(B)Y(S)\-FEB", "annual frequency, anchored end of February"
@@ -1692,7 +1692,7 @@ the end of the interval.
16921692
.. warning::
16931693

16941694
The default values for ``label`` and ``closed`` is '**left**' for all
1695-
frequency offsets except for 'ME', 'Y', 'Q', 'BME', 'BY', 'BQ', and 'W'
1695+
frequency offsets except for 'ME', 'Y', 'QE', 'BME', 'BY', 'BQ', and 'W'
16961696
which all have a default of 'right'.
16971697

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

doc/source/whatsnew/v0.18.0.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -808,11 +808,19 @@ Upsampling operations take you from a lower frequency to a higher frequency. The
808808
performed with the ``Resampler`` objects with :meth:`~Resampler.backfill`,
809809
:meth:`~Resampler.ffill`, :meth:`~Resampler.fillna` and :meth:`~Resampler.asfreq` methods.
810810

811-
.. ipython:: python
811+
.. code-block:: ipython
812812
813-
s = pd.Series(np.arange(5, dtype='int64'),
813+
In [89]: s = pd.Series(np.arange(5, dtype='int64'),
814814
index=pd.date_range('2010-01-01', periods=5, freq='Q'))
815-
s
815+
816+
In [90]: s
817+
Out[90]:
818+
2010-03-31 0
819+
2010-06-30 1
820+
2010-09-30 2
821+
2010-12-31 3
822+
2011-03-31 4
823+
Freq: Q-DEC, Length: 5, dtype: int64
816824
817825
Previously
818826

doc/source/whatsnew/v2.2.0.rst

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@ Other API changes
210210
Deprecations
211211
~~~~~~~~~~~~
212212

213-
Deprecate alias ``M`` in favour of ``ME`` for offsets
214-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
213+
Deprecate aliases ``M`` and ``Q`` in favour of ``ME`` and ``QE`` for offsets
214+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
215215

216216
The alias ``M`` is deprecated in favour of ``ME`` for offsets, please use ``ME`` for "month end" instead of ``M`` (:issue:`9586`)
217217

@@ -232,6 +232,25 @@ For example:
232232
233233
pd.date_range('2020-01-01', periods=3, freq='ME')
234234
235+
The alias ``Q`` is deprecated in favour of ``QE`` for offsets, please use ``QE`` for "quarter end" instead of ``Q`` (:issue:`9586`)
236+
237+
For example:
238+
239+
*Previous behavior*:
240+
241+
.. code-block:: ipython
242+
243+
In [8]: pd.date_range('2020-01-01', periods=3, freq='Q-NOV')
244+
Out[8]:
245+
DatetimeIndex(['2020-02-29', '2020-05-31', '2020-08-31'],
246+
dtype='datetime64[ns]', freq='Q-NOV')
247+
248+
*Future behavior*:
249+
250+
.. ipython:: python
251+
252+
pd.date_range('2020-01-01', periods=3, freq='QE-NOV')
253+
235254
Other Deprecations
236255
^^^^^^^^^^^^^^^^^^
237256
- Changed :meth:`Timedelta.resolution_string` to return ``h``, ``min``, ``s``, ``ms``, ``us``, and ``ns`` instead of ``H``, ``T``, ``S``, ``L``, ``U``, and ``N``, for compatibility with respective deprecations in frequency aliases (:issue:`52536`)

pandas/_libs/tslibs/dtypes.pyx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,19 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
201201
"us": "us",
202202
"ns": "ns",
203203
"h": "h",
204-
"Q": "Q",
204+
"QE": "Q",
205+
"QE-DEC": "Q-DEC",
206+
"QE-JAN": "Q-JAN",
207+
"QE-FEB": "Q-FEB",
208+
"QE-MAR": "Q-MAR",
209+
"QE-APR": "Q-APR",
210+
"QE-MAY": "Q-MAY",
211+
"QE-JUN": "Q-JUN",
212+
"QE-JUL": "Q-JUL",
213+
"QE-AUG": "Q-AUG",
214+
"QE-SEP": "Q-SEP",
215+
"QE-OCT": "Q-OCT",
216+
"QE-NOV": "Q-NOV",
205217
"W": "W",
206218
"ME": "M",
207219
"Y": "Y",
@@ -211,6 +223,19 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
211223
}
212224
OFFSET_DEPR_FREQSTR: dict[str, str]= {
213225
"M": "ME",
226+
"Q": "QE",
227+
"Q-DEC": "QE-DEC",
228+
"Q-JAN": "QE-JAN",
229+
"Q-FEB": "QE-FEB",
230+
"Q-MAR": "QE-MAR",
231+
"Q-APR": "QE-APR",
232+
"Q-MAY": "QE-MAY",
233+
"Q-JUN": "QE-JUN",
234+
"Q-JUL": "QE-JUL",
235+
"Q-AUG": "QE-AUG",
236+
"Q-SEP": "QE-SEP",
237+
"Q-OCT": "QE-OCT",
238+
"Q-NOV": "QE-NOV",
214239
}
215240
cdef dict c_OFFSET_TO_PERIOD_FREQSTR = OFFSET_TO_PERIOD_FREQSTR
216241
cdef dict c_OFFSET_DEPR_FREQSTR = OFFSET_DEPR_FREQSTR

pandas/_libs/tslibs/offsets.pyx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2767,7 +2767,7 @@ cdef class QuarterEnd(QuarterOffset):
27672767
Timestamp('2022-03-31 00:00:00')
27682768
"""
27692769
_default_starting_month = 3
2770-
_prefix = "Q"
2770+
_prefix = "QE"
27712771
_day_opt = "end"
27722772

27732773
cdef readonly:
@@ -4585,7 +4585,7 @@ prefix_mapping = {
45854585
Second, # 's'
45864586
Minute, # 'min'
45874587
Micro, # 'us'
4588-
QuarterEnd, # 'Q'
4588+
QuarterEnd, # 'QE'
45894589
QuarterBegin, # 'QS'
45904590
Milli, # 'ms'
45914591
Hour, # 'h'
@@ -4603,7 +4603,7 @@ opattern = re.compile(
46034603

46044604
_lite_rule_alias = {
46054605
"W": "W-SUN",
4606-
"Q": "Q-DEC",
4606+
"QE": "QE-DEC",
46074607

46084608
"Y": "Y-DEC", # YearEnd(month=12),
46094609
"YS": "YS-JAN", # YearBegin(month=1),
@@ -4617,7 +4617,7 @@ _lite_rule_alias = {
46174617
"ns": "ns",
46184618
}
46194619

4620-
_dont_uppercase = {"h", "bh", "cbh", "MS", "ms", "s", "me"}
4620+
_dont_uppercase = {"h", "bh", "cbh", "MS", "ms", "s", "me", "qe"}
46214621

46224622

46234623
INVALID_FREQ_ERR_MSG = "Invalid frequency: {0}"

pandas/core/indexes/accessors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ class DatetimeProperties(Properties):
284284
2 2
285285
dtype: int32
286286
287-
>>> quarters_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="q"))
287+
>>> quarters_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="QE"))
288288
>>> quarters_series
289289
0 2000-03-31
290290
1 2000-06-30

pandas/core/resample.py

Lines changed: 2 additions & 2 deletions
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", "Q", "BME", "BY", "BQ", "W"}
2133+
end_types = {"ME", "Y", "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:
@@ -2329,7 +2329,7 @@ def _adjust_bin_edges(
23292329
if self.freq.name in ("BME", "ME", "W") or self.freq.name.split("-")[0] in (
23302330
"BQ",
23312331
"BY",
2332-
"Q",
2332+
"QE",
23332333
"Y",
23342334
"W",
23352335
):

pandas/tests/arithmetic/test_datetime64.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ def test_dt64arr_add_dtlike_raises(self, tz_naive_fixture, box_with_array):
10761076
# Note: freq here includes both Tick and non-Tick offsets; this is
10771077
# relevant because historically integer-addition was allowed if we had
10781078
# a freq.
1079-
@pytest.mark.parametrize("freq", ["h", "D", "W", "2ME", "MS", "Q", "B", None])
1079+
@pytest.mark.parametrize("freq", ["h", "D", "W", "2ME", "MS", "QE", "B", None])
10801080
@pytest.mark.parametrize("dtype", [None, "uint8"])
10811081
def test_dt64arr_addsub_intlike(
10821082
self, request, dtype, box_with_array, freq, tz_naive_fixture

pandas/tests/arrays/test_datetimelike.py

Lines changed: 1 addition & 1 deletion
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", "Q", "Y"])
33+
@pytest.fixture(params=["D", "B", "W", "ME", "QE", "Y"])
3434
def freqstr(request):
3535
"""Fixture returning parametrized frequency in string format."""
3636
return request.param

pandas/tests/arrays/test_datetimes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,25 @@ def test_iter_zoneinfo_fold(self, tz):
746746
assert str(left) == str(right2)
747747
assert left.utcoffset() == right2.utcoffset()
748748

749+
@pytest.mark.parametrize(
750+
"freq, freq_depr",
751+
[
752+
("2ME", "2M"),
753+
("2QE", "2Q"),
754+
("2QE-SEP", "2Q-SEP"),
755+
],
756+
)
757+
def test_date_range_frequency_M_Q_deprecated(self, freq, freq_depr):
758+
# GH#9586
759+
depr_msg = (
760+
f"'{freq_depr[1:]}' will be deprecated, please use '{freq[1:]}' instead."
761+
)
762+
763+
expected = pd.date_range("1/1/2000", periods=4, freq=freq)
764+
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
765+
result = pd.date_range("1/1/2000", periods=4, freq=freq_depr)
766+
tm.assert_index_equal(result, expected)
767+
749768

750769
def test_factorize_sort_without_freq():
751770
dta = DatetimeArray._from_sequence([0, 2, 1])

0 commit comments

Comments
 (0)