Skip to content

Commit

Permalink
DEPR offsets: rename 'Q' to 'QE' (#55553)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
natmokval authored Oct 24, 2023
1 parent 6ef695f commit e0a8443
Show file tree
Hide file tree
Showing 30 changed files with 248 additions and 121 deletions.
30 changes: 15 additions & 15 deletions doc/source/user_guide/timeseries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ into ``freq`` keyword arguments. The available date offsets and associated frequ
:class:`~pandas.tseries.offsets.CBMonthBegin` or :class:`~pandas.tseries.offsets.CustomBusinessMonthBegin`, ``'CBMS'``, "custom business month begin"
:class:`~pandas.tseries.offsets.SemiMonthEnd`, ``'SM'``, "15th (or other day_of_month) and calendar month end"
:class:`~pandas.tseries.offsets.SemiMonthBegin`, ``'SMS'``, "15th (or other day_of_month) and calendar month begin"
:class:`~pandas.tseries.offsets.QuarterEnd`, ``'Q'``, "calendar quarter end"
:class:`~pandas.tseries.offsets.QuarterEnd`, ``'QE'``, "calendar quarter end"
:class:`~pandas.tseries.offsets.QuarterBegin`, ``'QS'``, "calendar quarter begin"
:class:`~pandas.tseries.offsets.BQuarterEnd`, ``'BQ``, "business quarter end"
:class:`~pandas.tseries.offsets.BQuarterBegin`, ``'BQS'``, "business quarter begin"
Expand Down Expand Up @@ -1254,7 +1254,7 @@ frequencies. We will refer to these aliases as *offset aliases*.
"SMS", "semi-month start frequency (1st and 15th)"
"BMS", "business month start frequency"
"CBMS", "custom business month start frequency"
"Q", "quarter end frequency"
"QE", "quarter end frequency"
"BQ", "business quarter end frequency"
"QS", "quarter start frequency"
"BQS", "business quarter start frequency"
Expand Down Expand Up @@ -1373,18 +1373,18 @@ For some frequencies you can specify an anchoring suffix:
"W\-THU", "weekly frequency (Thursdays)"
"W\-FRI", "weekly frequency (Fridays)"
"W\-SAT", "weekly frequency (Saturdays)"
"(B)Q(S)\-DEC", "quarterly frequency, year ends in December. Same as 'Q'"
"(B)Q(S)\-JAN", "quarterly frequency, year ends in January"
"(B)Q(S)\-FEB", "quarterly frequency, year ends in February"
"(B)Q(S)\-MAR", "quarterly frequency, year ends in March"
"(B)Q(S)\-APR", "quarterly frequency, year ends in April"
"(B)Q(S)\-MAY", "quarterly frequency, year ends in May"
"(B)Q(S)\-JUN", "quarterly frequency, year ends in June"
"(B)Q(S)\-JUL", "quarterly frequency, year ends in July"
"(B)Q(S)\-AUG", "quarterly frequency, year ends in August"
"(B)Q(S)\-SEP", "quarterly frequency, year ends in September"
"(B)Q(S)\-OCT", "quarterly frequency, year ends in October"
"(B)Q(S)\-NOV", "quarterly frequency, year ends in November"
"(B)Q(E)(S)\-DEC", "quarterly frequency, year ends in December. Same as 'QE'"
"(B)Q(E)(S)\-JAN", "quarterly frequency, year ends in January"
"(B)Q(E)(S)\-FEB", "quarterly frequency, year ends in February"
"(B)Q(E)(S)\-MAR", "quarterly frequency, year ends in March"
"(B)Q(E)(S)\-APR", "quarterly frequency, year ends in April"
"(B)Q(E)(S)\-MAY", "quarterly frequency, year ends in May"
"(B)Q(E)(S)\-JUN", "quarterly frequency, year ends in June"
"(B)Q(E)(S)\-JUL", "quarterly frequency, year ends in July"
"(B)Q(E)(S)\-AUG", "quarterly frequency, year ends in August"
"(B)Q(E)(S)\-SEP", "quarterly frequency, year ends in September"
"(B)Q(E)(S)\-OCT", "quarterly frequency, year ends in October"
"(B)Q(E)(S)\-NOV", "quarterly frequency, year ends in November"
"(B)Y(S)\-DEC", "annual frequency, anchored end of December. Same as 'Y'"
"(B)Y(S)\-JAN", "annual frequency, anchored end of January"
"(B)Y(S)\-FEB", "annual frequency, anchored end of February"
Expand Down Expand Up @@ -1692,7 +1692,7 @@ the end of the interval.
.. warning::

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

This might unintendedly lead to looking ahead, where the value for a later
Expand Down
14 changes: 11 additions & 3 deletions doc/source/whatsnew/v0.18.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -808,11 +808,19 @@ Upsampling operations take you from a lower frequency to a higher frequency. The
performed with the ``Resampler`` objects with :meth:`~Resampler.backfill`,
:meth:`~Resampler.ffill`, :meth:`~Resampler.fillna` and :meth:`~Resampler.asfreq` methods.

.. ipython:: python
.. code-block:: ipython
s = pd.Series(np.arange(5, dtype='int64'),
In [89]: s = pd.Series(np.arange(5, dtype='int64'),
index=pd.date_range('2010-01-01', periods=5, freq='Q'))
s
In [90]: s
Out[90]:
2010-03-31 0
2010-06-30 1
2010-09-30 2
2010-12-31 3
2011-03-31 4
Freq: Q-DEC, Length: 5, dtype: int64
Previously

Expand Down
23 changes: 21 additions & 2 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,8 @@ Other API changes
Deprecations
~~~~~~~~~~~~

Deprecate alias ``M`` in favour of ``ME`` for offsets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Deprecate aliases ``M`` and ``Q`` in favour of ``ME`` and ``QE`` for offsets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

Expand All @@ -232,6 +232,25 @@ For example:
pd.date_range('2020-01-01', periods=3, freq='ME')
The alias ``Q`` is deprecated in favour of ``QE`` for offsets, please use ``QE`` for "quarter end" instead of ``Q`` (:issue:`9586`)

For example:

*Previous behavior*:

.. code-block:: ipython
In [8]: pd.date_range('2020-01-01', periods=3, freq='Q-NOV')
Out[8]:
DatetimeIndex(['2020-02-29', '2020-05-31', '2020-08-31'],
dtype='datetime64[ns]', freq='Q-NOV')
*Future behavior*:

.. ipython:: python
pd.date_range('2020-01-01', periods=3, freq='QE-NOV')
Other Deprecations
^^^^^^^^^^^^^^^^^^
- 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`)
Expand Down
27 changes: 26 additions & 1 deletion pandas/_libs/tslibs/dtypes.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,19 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
"us": "us",
"ns": "ns",
"h": "h",
"Q": "Q",
"QE": "Q",
"QE-DEC": "Q-DEC",
"QE-JAN": "Q-JAN",
"QE-FEB": "Q-FEB",
"QE-MAR": "Q-MAR",
"QE-APR": "Q-APR",
"QE-MAY": "Q-MAY",
"QE-JUN": "Q-JUN",
"QE-JUL": "Q-JUL",
"QE-AUG": "Q-AUG",
"QE-SEP": "Q-SEP",
"QE-OCT": "Q-OCT",
"QE-NOV": "Q-NOV",
"W": "W",
"ME": "M",
"Y": "Y",
Expand All @@ -211,6 +223,19 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
}
OFFSET_DEPR_FREQSTR: dict[str, str]= {
"M": "ME",
"Q": "QE",
"Q-DEC": "QE-DEC",
"Q-JAN": "QE-JAN",
"Q-FEB": "QE-FEB",
"Q-MAR": "QE-MAR",
"Q-APR": "QE-APR",
"Q-MAY": "QE-MAY",
"Q-JUN": "QE-JUN",
"Q-JUL": "QE-JUL",
"Q-AUG": "QE-AUG",
"Q-SEP": "QE-SEP",
"Q-OCT": "QE-OCT",
"Q-NOV": "QE-NOV",
}
cdef dict c_OFFSET_TO_PERIOD_FREQSTR = OFFSET_TO_PERIOD_FREQSTR
cdef dict c_OFFSET_DEPR_FREQSTR = OFFSET_DEPR_FREQSTR
Expand Down
8 changes: 4 additions & 4 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2767,7 +2767,7 @@ cdef class QuarterEnd(QuarterOffset):
Timestamp('2022-03-31 00:00:00')
"""
_default_starting_month = 3
_prefix = "Q"
_prefix = "QE"
_day_opt = "end"

cdef readonly:
Expand Down Expand Up @@ -4585,7 +4585,7 @@ prefix_mapping = {
Second, # 's'
Minute, # 'min'
Micro, # 'us'
QuarterEnd, # 'Q'
QuarterEnd, # 'QE'
QuarterBegin, # 'QS'
Milli, # 'ms'
Hour, # 'h'
Expand All @@ -4603,7 +4603,7 @@ opattern = re.compile(

_lite_rule_alias = {
"W": "W-SUN",
"Q": "Q-DEC",
"QE": "QE-DEC",

"Y": "Y-DEC", # YearEnd(month=12),
"YS": "YS-JAN", # YearBegin(month=1),
Expand All @@ -4617,7 +4617,7 @@ _lite_rule_alias = {
"ns": "ns",
}

_dont_uppercase = {"h", "bh", "cbh", "MS", "ms", "s", "me"}
_dont_uppercase = {"h", "bh", "cbh", "MS", "ms", "s", "me", "qe"}


INVALID_FREQ_ERR_MSG = "Invalid frequency: {0}"
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/accessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class DatetimeProperties(Properties):
2 2
dtype: int32
>>> quarters_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="q"))
>>> quarters_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="QE"))
>>> quarters_series
0 2000-03-31
1 2000-06-30
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -2130,7 +2130,7 @@ def __init__(
else:
freq = to_offset(freq)

end_types = {"ME", "Y", "Q", "BME", "BY", "BQ", "W"}
end_types = {"ME", "Y", "QE", "BME", "BY", "BQ", "W"}
rule = freq.rule_code
if rule in end_types or ("-" in rule and rule[: rule.find("-")] in end_types):
if closed is None:
Expand Down Expand Up @@ -2329,7 +2329,7 @@ def _adjust_bin_edges(
if self.freq.name in ("BME", "ME", "W") or self.freq.name.split("-")[0] in (
"BQ",
"BY",
"Q",
"QE",
"Y",
"W",
):
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ def test_dt64arr_add_dtlike_raises(self, tz_naive_fixture, box_with_array):
# Note: freq here includes both Tick and non-Tick offsets; this is
# relevant because historically integer-addition was allowed if we had
# a freq.
@pytest.mark.parametrize("freq", ["h", "D", "W", "2ME", "MS", "Q", "B", None])
@pytest.mark.parametrize("freq", ["h", "D", "W", "2ME", "MS", "QE", "B", None])
@pytest.mark.parametrize("dtype", [None, "uint8"])
def test_dt64arr_addsub_intlike(
self, request, dtype, box_with_array, freq, tz_naive_fixture
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/arrays/test_datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


# TODO: more freq variants
@pytest.fixture(params=["D", "B", "W", "ME", "Q", "Y"])
@pytest.fixture(params=["D", "B", "W", "ME", "QE", "Y"])
def freqstr(request):
"""Fixture returning parametrized frequency in string format."""
return request.param
Expand Down
19 changes: 19 additions & 0 deletions pandas/tests/arrays/test_datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,25 @@ def test_iter_zoneinfo_fold(self, tz):
assert str(left) == str(right2)
assert left.utcoffset() == right2.utcoffset()

@pytest.mark.parametrize(
"freq, freq_depr",
[
("2ME", "2M"),
("2QE", "2Q"),
("2QE-SEP", "2Q-SEP"),
],
)
def test_date_range_frequency_M_Q_deprecated(self, freq, freq_depr):
# GH#9586
depr_msg = (
f"'{freq_depr[1:]}' will be deprecated, please use '{freq[1:]}' instead."
)

expected = pd.date_range("1/1/2000", periods=4, freq=freq)
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
result = pd.date_range("1/1/2000", periods=4, freq=freq_depr)
tm.assert_index_equal(result, expected)


def test_factorize_sort_without_freq():
dta = DatetimeArray._from_sequence([0, 2, 1])
Expand Down
23 changes: 17 additions & 6 deletions pandas/tests/frame/methods/test_asfreq.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,23 @@ def test_asfreq_2ME(self, freq, freq_half):
result = DataFrame({"s": Series([0.0, 2.0, 4.0], index=index)})
tm.assert_frame_equal(result, expected)

def test_asfreq_frequency_M_deprecated(self):
depr_msg = "'M' will be deprecated, please use 'ME' instead."
@pytest.mark.parametrize(
"freq, freq_depr",
[
("2ME", "2M"),
("2QE", "2Q"),
("2QE-SEP", "2Q-SEP"),
],
)
def test_asfreq_frequency_M_Q_deprecated(self, freq, freq_depr):
# GH#9586
depr_msg = (
f"'{freq_depr[1:]}' will be deprecated, please use '{freq[1:]}' instead."
)

index = date_range("1/1/2000", periods=4, freq="ME")
index = date_range("1/1/2000", periods=4, freq=f"{freq[1:]}")
df = DataFrame({"s": Series([0.0, 1.0, 2.0, 3.0], index=index)})
expected = df.asfreq(freq="5ME")
expected = df.asfreq(freq=freq)
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
result = df.asfreq(freq="5M")
tm.assert_frame_equal(result, expected)
result = df.asfreq(freq=freq_depr)
tm.assert_frame_equal(result, expected)
2 changes: 1 addition & 1 deletion pandas/tests/frame/test_nonunique_indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def test_setattr_columns_vs_construct_with_columns(self):
check(df, expected)

def test_setattr_columns_vs_construct_with_columns_datetimeindx(self):
idx = date_range("20130101", periods=4, freq="Q-NOV")
idx = date_range("20130101", periods=4, freq="QE-NOV")
df = DataFrame(
[[1, 1, 1, 5], [1, 1, 2, 5], [2, 1, 3, 5]], columns=["a", "a", "a", "a"]
)
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/groupby/test_timegrouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def test_timegrouper_with_reg_groups(self):
)
tm.assert_frame_equal(result, expected)

@pytest.mark.parametrize("freq", ["D", "ME", "Y", "Q-APR"])
@pytest.mark.parametrize("freq", ["D", "ME", "Y", "QE-APR"])
def test_timegrouper_with_reg_groups_freq(self, freq):
# GH 6764 multiple grouping with/without sort
df = DataFrame(
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/indexes/datetimes/methods/test_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"freq,expected",
[
("Y", "day"),
("Q", "day"),
("QE", "day"),
("ME", "day"),
("D", "day"),
("h", "hour"),
Expand Down
19 changes: 18 additions & 1 deletion pandas/tests/indexes/datetimes/methods/test_to_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_to_period_quarterly(self, month):
def test_to_period_quarterlyish(self, off):
rng = date_range("01-Jan-2012", periods=8, freq=off)
prng = rng.to_period()
assert prng.freq == "Q-DEC"
assert prng.freq == "QE-DEC"

@pytest.mark.parametrize("off", ["BY", "YS", "BYS"])
def test_to_period_annualish(self, off):
Expand Down Expand Up @@ -89,6 +89,23 @@ def test_dti_to_period_2monthish(self, freq_offset, freq_period):

tm.assert_index_equal(pi, period_range("2020-01", "2020-05", freq=freq_period))

@pytest.mark.parametrize(
"freq, freq_depr",
[
("2ME", "2M"),
("2QE", "2Q"),
("2QE-SEP", "2Q-SEP"),
],
)
def test_to_period_freq_deprecated(self, freq, freq_depr):
# GH#9586
msg = f"'{freq_depr[1:]}' will be deprecated, please use '{freq[1:]}' instead."

rng = date_range("01-Jan-2012", periods=8, freq=freq)
prng = rng.to_period()
with tm.assert_produces_warning(FutureWarning, match=msg):
assert prng.freq == freq_depr

def test_to_period_infer(self):
# https://github.com/pandas-dev/pandas/issues/33358
rng = date_range(
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/indexes/datetimes/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,8 @@ def test_constructor_int64_nocopy(self):
assert (index.asi8[50:100] != -1).all()

@pytest.mark.parametrize(
"freq", ["ME", "Q", "Y", "D", "B", "bh", "min", "s", "ms", "us", "h", "ns", "C"]
"freq",
["ME", "QE", "Y", "D", "B", "bh", "min", "s", "ms", "us", "h", "ns", "C"],
)
def test_from_freq_recreate_from_data(self, freq):
org = date_range(start="2001/02/01 09:00", freq=freq, periods=1)
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/indexes/datetimes/test_date_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ def test_3(self):
def test_precision_finer_than_offset(self):
# GH#9907
result1 = date_range(
start="2015-04-15 00:00:03", end="2016-04-22 00:00:00", freq="Q"
start="2015-04-15 00:00:03", end="2016-04-22 00:00:00", freq="QE"
)
result2 = date_range(
start="2015-04-15 00:00:03", end="2015-06-22 00:00:04", freq="W"
Expand All @@ -1042,7 +1042,7 @@ def test_precision_finer_than_offset(self):
"2015-06-21 00:00:03",
]
expected1 = DatetimeIndex(
expected1_list, dtype="datetime64[ns]", freq="Q-DEC", tz=None
expected1_list, dtype="datetime64[ns]", freq="QE-DEC", tz=None
)
expected2 = DatetimeIndex(
expected2_list, dtype="datetime64[ns]", freq="W-SUN", tz=None
Expand Down
Loading

0 comments on commit e0a8443

Please sign in to comment.