Skip to content

Commit cd02769

Browse files
committed
DEPR: PeriodDtype.freq
1 parent 6a6a1ba commit cd02769

File tree

7 files changed

+56
-15
lines changed

7 files changed

+56
-15
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ Other Deprecations
469469
- Deprecated strings ``w``, ``d``, ``MIN``, ``MS``, ``US`` and ``NS`` denoting units in :class:`Timedelta` in favour of ``W``, ``D``, ``min``, ``ms``, ``us`` and ``ns`` (:issue:`59051`)
470470
- Deprecated the ``arg`` parameter of ``Series.map``; pass the added ``func`` argument instead. (:issue:`61260`)
471471
- Deprecated using ``epoch`` date format in :meth:`DataFrame.to_json` and :meth:`Series.to_json`, use ``iso`` instead. (:issue:`57063`)
472+
- Deprecated :meth:`PeriodDtype.freq`, use ``dtype.unit`` instead (:issue:`??`)
472473

473474
.. ---------------------------------------------------------------------------
474475
.. _whatsnew_300.prior_deprecations:

pandas/core/arrays/datetimes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ def astype(self, dtype, copy: bool = True):
758758
)
759759

760760
elif isinstance(dtype, PeriodDtype):
761-
return self.to_period(freq=dtype.freq)
761+
return self.to_period(freq=dtype.unit)
762762
return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy)
763763

764764
# -----------------------------------------------------------------

pandas/core/arrays/period.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def __init__(self, values, dtype: Dtype | None = None, copy: bool = False) -> No
236236

237237
if isinstance(values, type(self)):
238238
if dtype is not None and dtype != values.dtype:
239-
raise raise_on_incompatible(values, dtype.freq)
239+
raise raise_on_incompatible(values, dtype.unit)
240240
values, dtype = values._ndarray, values.dtype
241241

242242
if not copy:
@@ -271,7 +271,7 @@ def _from_sequence(
271271
if dtype is not None:
272272
dtype = pandas_dtype(dtype)
273273
if dtype and isinstance(dtype, PeriodDtype):
274-
freq = dtype.freq
274+
freq = dtype.unit
275275
else:
276276
freq = None
277277

@@ -380,7 +380,7 @@ def freq(self) -> BaseOffset:
380380
"""
381381
Return the frequency object for this PeriodArray.
382382
"""
383-
return self.dtype.freq
383+
return self.dtype.unit
384384

385385
@property
386386
def freqstr(self) -> str:
@@ -945,7 +945,7 @@ def astype(self, dtype, copy: bool = True):
945945
else:
946946
return self.copy()
947947
if isinstance(dtype, PeriodDtype):
948-
return self.asfreq(dtype.freq)
948+
return self.asfreq(dtype.unit)
949949

950950
if lib.is_np_dtype(dtype, "M") or isinstance(dtype, DatetimeTZDtype):
951951
# GH#45038 match PeriodIndex behavior.
@@ -1227,7 +1227,7 @@ def period_array(
12271227
if isinstance(data_dtype, PeriodDtype):
12281228
out = PeriodArray(data)
12291229
if freq is not None:
1230-
if freq == data_dtype.freq:
1230+
if freq == data_dtype.unit:
12311231
return out
12321232
return out.asfreq(freq)
12331233
return out
@@ -1298,8 +1298,8 @@ def validate_dtype_freq(
12981298
if not isinstance(dtype, PeriodDtype):
12991299
raise ValueError("dtype must be PeriodDtype")
13001300
if freq is None:
1301-
freq = dtype.freq
1302-
elif freq != dtype.freq:
1301+
freq = dtype.unit
1302+
elif freq != dtype.unit:
13031303
raise IncompatibleFrequency("specified freq and dtype are different")
13041304
# error: Incompatible return value type (got "Union[BaseOffset, Any, None]",
13051305
# expected "BaseOffset")

pandas/core/dtypes/dtypes.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,33 @@ def __new__(cls, freq) -> PeriodDtype: # noqa: PYI034
10711071
def __reduce__(self) -> tuple[type_t[Self], tuple[str_type]]:
10721072
return type(self), (self.name,)
10731073

1074+
@property
1075+
def unit(self):
1076+
"""
1077+
The unit object of this PeriodDtype.
1078+
1079+
The `unit` property returns the `BaseOffset` object that represents the
1080+
unit of the PeriodDtype. This unit specifies the interval (e.g.,
1081+
daily, monthly, yearly) associated with the Period type. It is essential
1082+
for operations that depend on time-based calculations within a period index
1083+
or series.
1084+
1085+
See Also
1086+
--------
1087+
Period : Represents a period of time.
1088+
PeriodIndex : Immutable ndarray holding ordinal values indicating
1089+
regular periods.
1090+
PeriodDtype : An ExtensionDtype for Period data.
1091+
date_range : Return a fixed frequency range of dates.
1092+
1093+
Examples
1094+
--------
1095+
>>> dtype = pd.PeriodDtype("D")
1096+
>>> dtype.unit
1097+
<Day>
1098+
"""
1099+
return self._freq
1100+
10741101
@property
10751102
def freq(self) -> BaseOffset:
10761103
"""
@@ -1082,6 +1109,9 @@ def freq(self) -> BaseOffset:
10821109
for operations that depend on time-based calculations within a period index
10831110
or series.
10841111
1112+
.. deprecated: 3.0
1113+
Use dtype.unit instead.
1114+
10851115
See Also
10861116
--------
10871117
Period : Represents a period of time.
@@ -1096,6 +1126,11 @@ def freq(self) -> BaseOffset:
10961126
>>> dtype.freq
10971127
<Day>
10981128
"""
1129+
warnings.warn(
1130+
"PeriodDtype.freq is deprecated, use dtype.unit instead",
1131+
FutureWarning,
1132+
stacklevel=find_stack_level(),
1133+
)
10991134
return self._freq
11001135

11011136
@classmethod

pandas/io/json/_table_schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def convert_pandas_type_to_json_field(arr) -> dict[str, JSONSerializable]:
141141
field["constraints"] = {"enum": list(cats)}
142142
field["ordered"] = ordered
143143
elif isinstance(dtype, PeriodDtype):
144-
field["freq"] = dtype.freq.freqstr
144+
field["freq"] = dtype.unit.freqstr
145145
elif isinstance(dtype, DatetimeTZDtype):
146146
if timezones.is_utc(dtype.tz):
147147
field["tz"] = "UTC"

pandas/tests/dtypes/test_dtypes.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,11 @@ def test_construction(self):
426426

427427
for s in ["period[D]", "Period[D]", "D"]:
428428
dt = PeriodDtype(s)
429-
assert dt.freq == pd.tseries.offsets.Day()
429+
assert dt.unit == pd.tseries.offsets.Day()
430430

431431
for s in ["period[3D]", "Period[3D]", "3D"]:
432432
dt = PeriodDtype(s)
433-
assert dt.freq == pd.tseries.offsets.Day(3)
433+
assert dt.unit == pd.tseries.offsets.Day(3)
434434

435435
for s in [
436436
"period[26h]",
@@ -441,7 +441,7 @@ def test_construction(self):
441441
"1D2h",
442442
]:
443443
dt = PeriodDtype(s)
444-
assert dt.freq == pd.tseries.offsets.Hour(26)
444+
assert dt.unit == pd.tseries.offsets.Hour(26)
445445

446446
def test_cannot_use_custom_businessday(self):
447447
# GH#52534
@@ -565,10 +565,10 @@ def test_not_string(self):
565565
def test_perioddtype_caching_dateoffset_normalize(self):
566566
# GH 24121
567567
per_d = PeriodDtype(pd.offsets.YearEnd(normalize=True))
568-
assert per_d.freq.normalize
568+
assert per_d.unit.normalize
569569

570570
per_d2 = PeriodDtype(pd.offsets.YearEnd(normalize=False))
571-
assert not per_d2.freq.normalize
571+
assert not per_d2.unit.normalize
572572

573573
def test_dont_keep_ref_after_del(self):
574574
# GH 54184
@@ -577,6 +577,11 @@ def test_dont_keep_ref_after_del(self):
577577
del dtype
578578
assert ref() is None
579579

580+
def test_freq_deprecation(self, dtype):
581+
msg = "PeriodDtype.freq is deprecated, use dtype.unit instead"
582+
with tm.assert_produces_warning(FutureWarning, match=msg):
583+
dtype.freq
584+
580585

581586
class TestIntervalDtype(Base):
582587
@pytest.fixture

pandas/tests/extension/test_period.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def check_reduce(self, ser: pd.Series, op_name: str, skipna: bool):
9494
expected = exp_op(skipna=skipna)
9595
# error: Item "dtype[Any]" of "dtype[Any] | ExtensionDtype" has no
9696
# attribute "freq"
97-
freq = ser.dtype.freq # type: ignore[union-attr]
97+
freq = ser.dtype.unit # type: ignore[union-attr]
9898
expected = Period._from_ordinal(int(expected), freq=freq)
9999
tm.assert_almost_equal(result, expected)
100100

0 commit comments

Comments
 (0)