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

rename "Y" freq string to "YE" (pandas parity) #8629

Merged
merged 10 commits into from
Jan 22, 2024
9 changes: 9 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,19 @@ New Features
Breaking changes
~~~~~~~~~~~~~~~~

- Following pandas, :py:meth:`infer_freq` will return ``"YE"``, instead of ``"Y"`` (formerly ``"A"``).
This is to be consistent with the deprecation of the latter frequency string in pandas 2.2.
This is a follow up to :pull:`8415` (:issue:`8612`, :pull:`8629`).
By `Mathias Hauser <https://github.com/mathause>`_.

Deprecations
~~~~~~~~~~~~

- Following pandas, the frequency string ``"Y"`` (formerly ``"A"``) is deprecated in
favor of ``"YE"``. These strings are used, for example, in :py:func:`date_range`,
:py:func:`cftime_range`, :py:meth:`DataArray.resample`, and :py:meth:`Dataset.resample`
among others (:issue:`8612`, :pull:`8629`).
By `Mathias Hauser <https://github.com/mathause>`_.

Bug fixes
~~~~~~~~~
Expand Down
43 changes: 22 additions & 21 deletions xarray/coding/cftime_offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ def rollback(self, date):


class YearEnd(YearOffset):
_freq = "Y"
_freq = "YE"
_day_option = "end"
_default_month = 12

Expand Down Expand Up @@ -669,6 +669,7 @@ def _generate_anchored_offsets(base_freq, offset):
"A": YearEnd,
"AS": YearBegin,
"Y": YearEnd,
"YE": YearEnd,
"YS": YearBegin,
"Q": partial(QuarterEnd, month=12),
"QE": partial(QuarterEnd, month=12),
Expand All @@ -691,6 +692,7 @@ def _generate_anchored_offsets(base_freq, offset):
**_generate_anchored_offsets("A", YearEnd),
**_generate_anchored_offsets("YS", YearBegin),
**_generate_anchored_offsets("Y", YearEnd),
**_generate_anchored_offsets("YE", YearEnd),
**_generate_anchored_offsets("QS", QuarterBegin),
**_generate_anchored_offsets("Q", QuarterEnd),
**_generate_anchored_offsets("QE", QuarterEnd),
Expand All @@ -716,7 +718,8 @@ def _generate_anchored_deprecated_frequencies(deprecated, recommended):


_DEPRECATED_FREQUENICES = {
"A": "Y",
"A": "YE",
"Y": "YE",
"AS": "YS",
"Q": "QE",
"M": "ME",
Expand All @@ -725,7 +728,8 @@ def _generate_anchored_deprecated_frequencies(deprecated, recommended):
"S": "s",
"L": "ms",
"U": "us",
**_generate_anchored_deprecated_frequencies("A", "Y"),
**_generate_anchored_deprecated_frequencies("A", "YE"),
**_generate_anchored_deprecated_frequencies("Y", "YE"),
**_generate_anchored_deprecated_frequencies("AS", "YS"),
**_generate_anchored_deprecated_frequencies("Q", "QE"),
}
Expand Down Expand Up @@ -979,7 +983,7 @@ def cftime_range(
+--------+--------------------------+
| Alias | Description |
+========+==========================+
| Y | Year-end frequency |
| YE | Year-end frequency |
+--------+--------------------------+
| YS | Year-start frequency |
+--------+--------------------------+
Expand Down Expand Up @@ -1009,29 +1013,29 @@ def cftime_range(
+------------+--------------------------------------------------------------------+
| Alias | Description |
+============+====================================================================+
| Y(S)-JAN | Annual frequency, anchored at the end (or beginning) of January |
| Y(E,S)-JAN | Annual frequency, anchored at the (end, beginning) of January |
+------------+--------------------------------------------------------------------+
| Y(S)-FEB | Annual frequency, anchored at the end (or beginning) of February |
| Y(E,S)-FEB | Annual frequency, anchored at the (end, beginning) of February |
+------------+--------------------------------------------------------------------+
| Y(S)-MAR | Annual frequency, anchored at the end (or beginning) of March |
| Y(E,S)-MAR | Annual frequency, anchored at the (end, beginning) of March |
+------------+--------------------------------------------------------------------+
| Y(S)-APR | Annual frequency, anchored at the end (or beginning) of April |
| Y(E,S)-APR | Annual frequency, anchored at the (end, beginning) of April |
+------------+--------------------------------------------------------------------+
| Y(S)-MAY | Annual frequency, anchored at the end (or beginning) of May |
| Y(E,S)-MAY | Annual frequency, anchored at the (end, beginning) of May |
+------------+--------------------------------------------------------------------+
| Y(S)-JUN | Annual frequency, anchored at the end (or beginning) of June |
| Y(E,S)-JUN | Annual frequency, anchored at the (end, beginning) of June |
+------------+--------------------------------------------------------------------+
| Y(S)-JUL | Annual frequency, anchored at the end (or beginning) of July |
| Y(E,S)-JUL | Annual frequency, anchored at the (end, beginning) of July |
+------------+--------------------------------------------------------------------+
| Y(S)-AUG | Annual frequency, anchored at the end (or beginning) of August |
| Y(E,S)-AUG | Annual frequency, anchored at the (end, beginning) of August |
+------------+--------------------------------------------------------------------+
| Y(S)-SEP | Annual frequency, anchored at the end (or beginning) of September |
| Y(E,S)-SEP | Annual frequency, anchored at the (end, beginning) of September |
+------------+--------------------------------------------------------------------+
| Y(S)-OCT | Annual frequency, anchored at the end (or beginning) of October |
| Y(E,S)-OCT | Annual frequency, anchored at the (end, beginning) of October |
+------------+--------------------------------------------------------------------+
| Y(S)-NOV | Annual frequency, anchored at the end (or beginning) of November |
| Y(E,S)-NOV | Annual frequency, anchored at the (end, beginning) of November |
+------------+--------------------------------------------------------------------+
| Y(S)-DEC | Annual frequency, anchored at the end (or beginning) of December |
| Y(E,S)-DEC | Annual frequency, anchored at the (end, beginning) of December |
+------------+--------------------------------------------------------------------+
| Q(E,S)-JAN | Quarter frequency, anchored at the (end, beginning) of January |
+------------+--------------------------------------------------------------------+
Expand Down Expand Up @@ -1311,11 +1315,8 @@ def date_range_like(source, calendar, use_cftime=None):
freq = freq.replace("QE", "Q")
elif isinstance(freq_as_offset, YearBegin) and "YS" in freq:
freq = freq.replace("YS", "AS")
elif isinstance(freq_as_offset, YearEnd) and "Y-" in freq:
# Check for and replace "Y-" instead of just "Y" to prevent
# corrupting anchored offsets that contain "Y" in the month
# abbreviation, e.g. "Y-MAY" -> "A-MAY".
freq = freq.replace("Y-", "A-")
elif isinstance(freq_as_offset, YearEnd) and "YE" in freq:
freq = freq.replace("YE", "A")

use_cftime = _should_cftime_be_used(source, calendar, use_cftime)

Expand Down
12 changes: 7 additions & 5 deletions xarray/tests/test_cftime_offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_year_offset_constructor_invalid_month(offset, invalid_month, exception)
(MonthBegin(), "MS"),
(MonthEnd(), "ME"),
(YearBegin(), "YS-JAN"),
(YearEnd(), "Y-DEC"),
(YearEnd(), "YE-DEC"),
(QuarterBegin(), "QS-MAR"),
(QuarterEnd(), "QE-MAR"),
(Day(), "D"),
Expand Down Expand Up @@ -1387,7 +1387,7 @@ def test_date_range_errors() -> None:
("2020-02-01", "ME", "noleap", "gregorian", True, "2020-02-29", True),
("2020-02-01", "QE-DEC", "noleap", "gregorian", True, "2020-03-31", True),
("2020-02-01", "YS-FEB", "noleap", "gregorian", True, "2020-02-01", True),
("2020-02-01", "Y-FEB", "noleap", "gregorian", True, "2020-02-29", True),
("2020-02-01", "YE-FEB", "noleap", "gregorian", True, "2020-02-29", True),
("2020-02-28", "3h", "all_leap", "gregorian", False, "2020-02-28", True),
("2020-03-30", "ME", "360_day", "gregorian", False, "2020-03-31", True),
("2020-03-31", "ME", "gregorian", "360_day", None, "2020-03-30", False),
Expand All @@ -1409,8 +1409,8 @@ def test_date_range_like(start, freq, cal_src, cal_tgt, use_cftime, exp0, exp_pd
elif "YS" in freq:
freq = freq.replace("YS", "AS")
expected_pandas_freq = freq
elif "Y-" in freq:
freq = freq.replace("Y-", "A-")
elif "YE-" in freq:
freq = freq.replace("YE-", "A-")
expected_pandas_freq = freq
elif "h" in freq:
expected_pandas_freq = freq.replace("h", "H")
Expand Down Expand Up @@ -1534,7 +1534,9 @@ def test_cftime_or_date_range_inclusive_None(function) -> None:
np.testing.assert_equal(result_None.values, result_both.values)


@pytest.mark.parametrize("freq", ["A", "AS", "Q", "M", "H", "T", "S", "L", "U"])
@pytest.mark.parametrize(
"freq", ["A", "AS", "Q", "M", "H", "T", "S", "L", "U", "Y", "A-MAY"]
)
def test_to_offset_deprecation_warning(freq):
# Test for deprecations outlined in GitHub issue #8394
with pytest.warns(FutureWarning, match="is deprecated"):
Expand Down
Loading