Skip to content

Commit f833723

Browse files
committed
Fix pandas deprecation warnings
1 parent f87f0b2 commit f833723

20 files changed

+168
-61
lines changed

_stubtest/allowlist.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ xarray\.core\.dataset\.DatasetResample$
107107

108108
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.date_type$
109109
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.day$
110+
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.day_of_week$
110111
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.dayofweek$
112+
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.day_of_year$
111113
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.dayofyear$
112114
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.days_in_month$
113115
xarray\.core\.(dataarray|dataset)\.CFTimeIndex\.hour$

doc/api-hidden.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@
114114
core.accessor_dt.DatetimeAccessor.date
115115
core.accessor_dt.DatetimeAccessor.day
116116
core.accessor_dt.DatetimeAccessor.dayofweek
117+
core.accessor_dt.DatetimeAccessor.day_of_week
117118
core.accessor_dt.DatetimeAccessor.dayofyear
119+
core.accessor_dt.DatetimeAccessor.day_of_year
118120
core.accessor_dt.DatetimeAccessor.days_in_month
119121
core.accessor_dt.DatetimeAccessor.daysinmonth
120122
core.accessor_dt.DatetimeAccessor.hour
@@ -409,6 +411,8 @@
409411
CFTimeIndex.ceil
410412
CFTimeIndex.contains
411413
CFTimeIndex.copy
414+
CFTimeIndex.day_of_week
415+
CFTimeIndex.day_of_year
412416
CFTimeIndex.days_in_month
413417
CFTimeIndex.delete
414418
CFTimeIndex.difference

doc/api/dataarray.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,10 @@ Datetimelike properties
272272
DataArray.dt.second
273273
DataArray.dt.microsecond
274274
DataArray.dt.nanosecond
275+
DataArray.dt.day_of_week
275276
DataArray.dt.dayofweek
276277
DataArray.dt.weekday
278+
DataArray.dt.day_of_year
277279
DataArray.dt.dayofyear
278280
DataArray.dt.quarter
279281
DataArray.dt.days_in_month

doc/getting-started-guide/why-xarray.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ powerful and concise interface. For example:
2828
dimensions (array broadcasting) based on dimension names, not shape.
2929
- Easily use the `split-apply-combine <https://vita.had.co.nz/papers/plyr.pdf>`_
3030
paradigm with ``groupby``:
31-
``x.groupby('time.dayofyear').mean()``.
31+
``x.groupby('time.day_of_year').mean()``.
3232
- Database-like alignment based on coordinate labels that smoothly
3333
handles missing values: ``x, y = xr.align(x, y, join='outer')``.
3434
- Keep track of arbitrary metadata in the form of a Python dictionary:

doc/user-guide/time-series.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,15 @@ given ``DataArray`` can be quickly computed using a special ``.dt`` accessor.
150150

151151
.. jupyter-execute::
152152

153-
ds.time.dt.dayofweek
153+
ds.time.dt.day_of_week
154154

155155
The ``.dt`` accessor works on both coordinate dimensions as well as
156156
multi-dimensional data.
157157

158158
Xarray also supports a notion of "virtual" or "derived" coordinates for
159159
`datetime components`__ implemented by pandas, including "year", "month",
160-
"day", "hour", "minute", "second", "dayofyear", "week", "dayofweek", "weekday"
161-
and "quarter":
160+
"day", "hour", "minute", "second", "day_of_year", "week", "day_of_week", and
161+
"quarter":
162162

163163
__ https://pandas.pydata.org/pandas-docs/stable/api.html#time-date-components
164164

@@ -168,7 +168,7 @@ __ https://pandas.pydata.org/pandas-docs/stable/api.html#time-date-components
168168

169169
.. jupyter-execute::
170170

171-
ds["time.dayofyear"]
171+
ds["time.day_of_year"]
172172

173173
For use as a derived coordinate, xarray adds ``'season'`` to the list of
174174
datetime components supported by pandas:

doc/user-guide/weather-climate.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
184184

185185
- Access of basic datetime components via the ``dt`` accessor (in this case
186186
just "year", "month", "day", "hour", "minute", "second", "microsecond",
187-
"season", "dayofyear", "dayofweek", and "days_in_month") with the addition
188-
of "calendar", absent from pandas:
187+
"season", "day_of_year", "day_of_week", and "days_in_month") with the
188+
addition of "calendar", absent from pandas:
189189

190190
.. jupyter-execute::
191191

@@ -201,11 +201,11 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
201201

202202
.. jupyter-execute::
203203

204-
da.time.dt.dayofyear
204+
da.time.dt.day_of_year
205205

206206
.. jupyter-execute::
207207

208-
da.time.dt.dayofweek
208+
da.time.dt.day_of_week
209209

210210
.. jupyter-execute::
211211

xarray/coding/calendar_ops.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ def _interpolate_day_of_year(times, target_calendar):
249249
source_calendar = times.dt.calendar
250250
return np.round(
251251
_days_in_year(times.dt.year, target_calendar)
252-
* times.dt.dayofyear
252+
* times.dt.day_of_year
253253
/ _days_in_year(times.dt.year, source_calendar)
254254
).astype(int)
255255

@@ -272,7 +272,7 @@ def _random_day_of_year(time, target_calendar, use_cftime):
272272
new_doy = np.insert(new_doy, rm_idx - np.arange(5), -1)
273273
if _days_in_year(year, source_calendar) == 366:
274274
new_doy = np.insert(new_doy, 60, -1)
275-
return new_doy[time.dt.dayofyear - 1]
275+
return new_doy[time.dt.day_of_year - 1]
276276

277277

278278
def _convert_to_new_calendar_with_new_day_of_year(

xarray/coding/cftime_offsets.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,10 +1623,18 @@ def date_range_like(source, calendar, use_cftime=None):
16231623
end = convert_time_or_go_back(source_end, date_type)
16241624

16251625
# For the cases where the source ends on the end of the month, we expect the same in the new calendar.
1626-
if source_end.day == source_end.daysinmonth and isinstance(
1626+
if isinstance(source_end, pd.Timestamp):
1627+
source_end_days_in_month = source_end.days_in_month
1628+
else:
1629+
source_end_days_in_month = source_end.daysinmonth
1630+
if isinstance(end, pd.Timestamp):
1631+
end_days_in_month = end.days_in_month
1632+
else:
1633+
end_days_in_month = end.daysinmonth
1634+
if source_end.day == source_end_days_in_month and isinstance(
16271635
freq_as_offset, YearEnd | QuarterEnd | MonthEnd | Day
16281636
):
1629-
end = end.replace(day=end.daysinmonth)
1637+
end = end.replace(day=end_days_in_month)
16301638

16311639
return date_range(
16321640
start=start.isoformat(),

xarray/coding/cftimeindex.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,12 @@ def get_date_field(datetimes, field):
127127
return np.array([getattr(date, field) for date in datetimes], dtype=np.int64)
128128

129129

130-
def _field_accessor(name, docstring=None, min_cftime_version="0.0"):
130+
def _field_accessor(
131+
name: str,
132+
docstring: str | None = None,
133+
min_cftime_version: str = "0.0",
134+
deprecation_pair: tuple[str, str] | None = None,
135+
):
131136
"""Adapted from pandas.tseries.index._field_accessor"""
132137

133138
def f(self, min_cftime_version=min_cftime_version):
@@ -136,6 +141,14 @@ def f(self, min_cftime_version=min_cftime_version):
136141
else:
137142
cftime = attempt_import("cftime")
138143

144+
if deprecation_pair is not None:
145+
original, replacement = deprecation_pair
146+
emit_user_level_warning(
147+
f"CFTimeIndex.{original} is deprecated and will be removed in "
148+
f"a future version. Use CFTimeIndex.{replacement} instead",
149+
FutureWarning,
150+
)
151+
139152
if Version(cftime.__version__) >= Version(min_cftime_version):
140153
return get_date_field(self._data, name)
141154
else:
@@ -249,9 +262,23 @@ class CFTimeIndex(pd.Index):
249262
second = _field_accessor("second", "The seconds of the datetime")
250263
microsecond = _field_accessor("microsecond", "The microseconds of the datetime")
251264
dayofyear = _field_accessor(
265+
"dayofyr",
266+
"The ordinal day of year of the datetime",
267+
"1.0.2.1",
268+
("dayofyear", "day_of_year"),
269+
)
270+
dayofweek = _field_accessor(
271+
"dayofwk",
272+
"The day of week of the datetime",
273+
"1.0.2.1",
274+
("dayofweek", "day_of_week"),
275+
)
276+
day_of_year = _field_accessor(
252277
"dayofyr", "The ordinal day of year of the datetime", "1.0.2.1"
253278
)
254-
dayofweek = _field_accessor("dayofwk", "The day of week of the datetime", "1.0.2.1")
279+
day_of_week = _field_accessor(
280+
"dayofwk", "The day of week of the datetime", "1.0.2.1"
281+
)
255282
days_in_month = _field_accessor(
256283
"daysinmonth", "The number of days in the month of the datetime", "1.1.0.0"
257284
)

xarray/core/accessor_dt.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
is_np_timedelta_like,
1717
)
1818
from xarray.core.types import T_DataArray
19+
from xarray.core.utils import emit_user_level_warning
1920
from xarray.core.variable import IndexVariable, Variable
2021
from xarray.namedarray.utils import is_duck_dask_array
2122

@@ -338,8 +339,8 @@ class DatetimeAccessor(TimeAccessor[T_DataArray]):
338339
* time (time) datetime64[us] 80B 2000-01-01 2000-01-02 ... 2000-01-10
339340
>>> ts.dt # doctest: +ELLIPSIS
340341
<xarray.core.accessor_dt.DatetimeAccessor object at 0x...>
341-
>>> ts.dt.dayofyear
342-
<xarray.DataArray 'dayofyear' (time: 10)> Size: 80B
342+
>>> ts.dt.day_of_year
343+
<xarray.DataArray 'day_of_year' (time: 10)> Size: 80B
343344
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
344345
Coordinates:
345346
* time (time) datetime64[us] 80B 2000-01-01 2000-01-02 ... 2000-01-10
@@ -465,17 +466,45 @@ def weekofyear(self) -> DataArray:
465466

466467
week = weekofyear
467468

469+
@property
470+
def day_of_week(self) -> T_DataArray:
471+
"""The day of the week with Monday=0, Sunday=6"""
472+
return self._date_field("day_of_week", np.int64)
473+
468474
@property
469475
def dayofweek(self) -> T_DataArray:
470476
"""The day of the week with Monday=0, Sunday=6"""
471-
return self._date_field("dayofweek", np.int64)
477+
emit_user_level_warning(
478+
"dt.dayofweek is deprecated and will be removed in a future "
479+
"version. Use dt.day_of_week instead.",
480+
FutureWarning,
481+
)
482+
return self._date_field("day_of_week", np.int64)
472483

473-
weekday = dayofweek
484+
@property
485+
def weekday(self) -> T_DataArray:
486+
"""The day of the week with Monday=0, Sunday=6"""
487+
emit_user_level_warning(
488+
"dt.weekday is deprecated and will be removed in a "
489+
"future version. Use dt.day_of_week instead.",
490+
FutureWarning,
491+
)
492+
return self._date_field("day_of_week", np.int64)
493+
494+
@property
495+
def day_of_year(self) -> T_DataArray:
496+
"""The ordinal day of the year"""
497+
return self._date_field("day_of_year", np.int64)
474498

475499
@property
476500
def dayofyear(self) -> T_DataArray:
477501
"""The ordinal day of the year"""
478-
return self._date_field("dayofyear", np.int64)
502+
emit_user_level_warning(
503+
"dt.dayofyear is deprecated and will be removed in a future "
504+
"version. Use dt.day_of_year instead.",
505+
FutureWarning,
506+
)
507+
return self._date_field("day_of_year", np.int64)
479508

480509
@property
481510
def quarter(self) -> T_DataArray:
@@ -487,7 +516,15 @@ def days_in_month(self) -> T_DataArray:
487516
"""The number of days in the month"""
488517
return self._date_field("days_in_month", np.int64)
489518

490-
daysinmonth = days_in_month
519+
@property
520+
def daysinmonth(self) -> T_DataArray:
521+
"""The number of days in the month"""
522+
emit_user_level_warning(
523+
"dt.daysinmonth is deprecated and will be removed in a future "
524+
"version. Use dt.days_in_month instead.",
525+
FutureWarning,
526+
)
527+
return self._date_field("days_in_month", np.int64)
491528

492529
@property
493530
def season(self) -> T_DataArray:

0 commit comments

Comments
 (0)