Skip to content

Commit

Permalink
rename "Y" freq string to "YE" (pandas parity) (#8629)
Browse files Browse the repository at this point in the history
* rename "Y" freq string to "YE" (pandas parity)

* Update xarray/coding/cftime_offsets.py

Co-authored-by: Spencer Clark <spencerkclark@gmail.com>

* fix table

* changelog

* remove unneeded elif branch

---------

Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com>
Co-authored-by: Spencer Clark <spencerkclark@gmail.com>
  • Loading branch information
3 people authored Jan 22, 2024
1 parent e571d1c commit 5a92d48
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
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

0 comments on commit 5a92d48

Please sign in to comment.