Skip to content

Commit c25269e

Browse files
jbrockmendelproost
authored andcommitted
DEPR: setting DTI.freq, DTI.offset, DTI.asobject (pandas-dev#29801)
1 parent d425863 commit c25269e

File tree

14 files changed

+36
-71
lines changed

14 files changed

+36
-71
lines changed

doc/source/whatsnew/v1.0.0.rst

+3
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,9 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
439439
- Removed the previously deprecated :meth:`DataFrame.get_ftype_counts`, :meth:`Series.get_ftype_counts` (:issue:`18243`)
440440
- Removed the previously deprecated :meth:`Index.get_duplicated`, use ``idx[idx.duplicated()].unique()`` instead (:issue:`20239`)
441441
- Removed the previously deprecated :meth:`Series.clip_upper`, :meth:`Series.clip_lower`, :meth:`DataFrame.clip_upper`, :meth:`DataFrame.clip_lower` (:issue:`24203`)
442+
- Removed the ability to alter :attr:`DatetimeIndex.freq`, :attr:`TimedeltaIndex.freq`, or :attr:`PeriodIndex.freq` (:issue:`20772`)
443+
- Removed the previously deprecated :attr:`DatetimeIndex.offset` (:issue:`20730`)
444+
- Removed the previously deprecated :meth:`DatetimeIndex.asobject`, :meth:`TimedeltaIndex.asobject`, :meth:`PeriodIndex.asobject`, use ``astype(object)`` instead (:issue:`29801`)
442445
- Removed previously deprecated "order" argument from :func:`factorize` (:issue:`19751`)
443446
- Removed previously deprecated "v" argument from :meth:`FrozenNDarray.searchsorted`, use "value" instead (:issue:`22672`)
444447
- :func:`read_stata` and :meth:`DataFrame.to_stata` no longer supports the "encoding" argument (:issue:`21400`)

pandas/core/indexes/datetimelike.py

+7-26
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"""
44
import operator
55
from typing import Set
6-
import warnings
76

87
import numpy as np
98

@@ -104,11 +103,6 @@ def freq(self):
104103
"""
105104
return self._data.freq
106105

107-
@freq.setter
108-
def freq(self, value):
109-
# validation is handled by _data setter
110-
self._data.freq = value
111-
112106
@property
113107
def freqstr(self):
114108
"""
@@ -332,23 +326,6 @@ def take(self, indices, axis=0, allow_fill=True, fill_value=None, **kwargs):
332326
_na_value = NaT
333327
"""The expected NA value to use with this index."""
334328

335-
@property
336-
def asobject(self):
337-
"""
338-
Return object Index which contains boxed values.
339-
340-
.. deprecated:: 0.23.0
341-
Use ``astype(object)`` instead.
342-
343-
*this is an internal non-public method*
344-
"""
345-
warnings.warn(
346-
"'asobject' is deprecated. Use 'astype(object)' instead",
347-
FutureWarning,
348-
stacklevel=2,
349-
)
350-
return self.astype(object)
351-
352329
def _convert_tolerance(self, tolerance, target):
353330
tolerance = np.asarray(to_timedelta(tolerance).to_numpy())
354331

@@ -612,7 +589,8 @@ def intersection(self, other, sort=False):
612589
result = Index.intersection(self, other, sort=sort)
613590
if isinstance(result, type(self)):
614591
if result.freq is None:
615-
result.freq = to_offset(result.inferred_freq)
592+
# TODO: find a less code-smelly way to set this
593+
result._data._freq = to_offset(result.inferred_freq)
616594
return result
617595

618596
elif (
@@ -626,15 +604,18 @@ def intersection(self, other, sort=False):
626604

627605
# Invalidate the freq of `result`, which may not be correct at
628606
# this point, depending on the values.
629-
result.freq = None
607+
608+
# TODO: find a less code-smelly way to set this
609+
result._data._freq = None
630610
if hasattr(self, "tz"):
631611
result = self._shallow_copy(
632612
result._values, name=result.name, tz=result.tz, freq=None
633613
)
634614
else:
635615
result = self._shallow_copy(result._values, name=result.name, freq=None)
636616
if result.freq is None:
637-
result.freq = to_offset(result.inferred_freq)
617+
# TODO: find a less code-smelly way to set this
618+
result._data._freq = to_offset(result.inferred_freq)
638619
return result
639620

640621
# to make our life easier, "sort" the two ranges

pandas/core/indexes/datetimes.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ def _convert_for_op(self, value):
467467
@Appender(Index.difference.__doc__)
468468
def difference(self, other, sort=None):
469469
new_idx = super().difference(other, sort=sort)
470-
new_idx.freq = None
470+
new_idx._data._freq = None
471471
return new_idx
472472

473473
# --------------------------------------------------------------------
@@ -522,7 +522,7 @@ def _union(self, other, sort):
522522
if result.freq is None and (
523523
this.freq is not None or other.freq is not None
524524
):
525-
result.freq = to_offset(result.inferred_freq)
525+
result._data._freq = to_offset(result.inferred_freq)
526526
return result
527527

528528
def union_many(self, others):
@@ -1208,7 +1208,7 @@ def offset(self, value):
12081208
)
12091209
)
12101210
warnings.warn(msg, FutureWarning, stacklevel=2)
1211-
self.freq = value
1211+
self._data.freq = value
12121212

12131213
def __getitem__(self, key):
12141214
result = self._data.__getitem__(key)

pandas/core/indexes/period.py

-15
Original file line numberDiff line numberDiff line change
@@ -313,21 +313,6 @@ def values(self):
313313
def freq(self) -> DateOffset:
314314
return self._data.freq
315315

316-
@freq.setter
317-
def freq(self, value):
318-
value = Period._maybe_convert_freq(value)
319-
# TODO: When this deprecation is enforced, PeriodIndex.freq can
320-
# be removed entirely, and we'll just inherit.
321-
msg = (
322-
"Setting {cls}.freq has been deprecated and will be "
323-
"removed in a future version; use {cls}.asfreq instead. "
324-
"The {cls}.freq setter is not guaranteed to work."
325-
)
326-
warnings.warn(msg.format(cls=type(self).__name__), FutureWarning, stacklevel=2)
327-
# PeriodArray._freq isn't actually mutable. We set the private _freq
328-
# here, but people shouldn't be doing this anyway.
329-
self._data._freq = value
330-
331316
def _shallow_copy(self, values=None, **kwargs):
332317
# TODO: simplify, figure out type of values
333318
if values is None:

pandas/core/indexes/timedeltas.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ def _union(self, other, sort):
356356
result = Index._union(this, other, sort=sort)
357357
if isinstance(result, TimedeltaIndex):
358358
if result.freq is None:
359-
result.freq = to_offset(result.inferred_freq)
359+
# TODO: find a less code-smelly way to set this
360+
result._data._freq = to_offset(result.inferred_freq)
360361
return result
361362

362363
def join(self, other, how="left", level=None, return_indexers=False, sort=False):
@@ -409,7 +410,8 @@ def intersection(self, other, sort=False):
409410
@Appender(Index.difference.__doc__)
410411
def difference(self, other, sort=None):
411412
new_idx = super().difference(other, sort=sort)
412-
new_idx.freq = None
413+
# TODO: find a less code-smelly way to set this
414+
new_idx._data._freq = None
413415
return new_idx
414416

415417
def _wrap_joined_index(self, joined, other):

pandas/core/resample.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,8 @@ def _downsample(self, how, **kwargs):
10801080
if not len(ax):
10811081
# reset to the new freq
10821082
obj = obj.copy()
1083-
obj.index.freq = self.freq
1083+
# TODO: find a less code-smelly way to set this
1084+
obj.index._data._freq = self.freq
10841085
return obj
10851086

10861087
# do we have a regular frequency

pandas/tests/arrays/categorical/test_constructors.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ def test_constructor_with_datetimelike(self, dtl):
311311
c = Categorical(s)
312312

313313
expected = type(dtl)(s)
314-
expected.freq = None
314+
expected._data.freq = None
315315

316316
tm.assert_index_equal(c.categories, expected)
317317
tm.assert_numpy_array_equal(c.codes, np.arange(5, dtype="int8"))
@@ -322,7 +322,7 @@ def test_constructor_with_datetimelike(self, dtl):
322322
c = Categorical(s2)
323323

324324
expected = type(dtl)(s2.dropna())
325-
expected.freq = None
325+
expected._data.freq = None
326326

327327
tm.assert_index_equal(c.categories, expected)
328328

pandas/tests/indexes/datetimelike.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_map_dictlike(self, mapper):
8181

8282
# don't compare the freqs
8383
if isinstance(expected, pd.DatetimeIndex):
84-
expected.freq = None
84+
expected._data.freq = None
8585

8686
result = index.map(mapper(expected, index))
8787
tm.assert_index_equal(result, expected)
@@ -95,10 +95,3 @@ def test_map_dictlike(self, mapper):
9595
expected = pd.Index([np.nan] * len(index))
9696
result = index.map(mapper([], []))
9797
tm.assert_index_equal(result, expected)
98-
99-
def test_asobject_deprecated(self):
100-
# GH18572
101-
d = self.create_index()
102-
with tm.assert_produces_warning(FutureWarning):
103-
i = d.asobject
104-
assert isinstance(i, pd.Index)

pandas/tests/indexes/datetimes/test_date_range.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ def test_daterange_bug_456(self):
798798
# GH #456
799799
rng1 = bdate_range("12/5/2011", "12/5/2011")
800800
rng2 = bdate_range("12/2/2011", "12/5/2011")
801-
rng2.freq = BDay()
801+
rng2._data.freq = BDay() # TODO: shouldnt this already be set?
802802

803803
result = rng1.union(rng2)
804804
assert isinstance(result, DatetimeIndex)
@@ -855,7 +855,7 @@ def test_daterange_bug_456(self):
855855
# GH #456
856856
rng1 = bdate_range("12/5/2011", "12/5/2011", freq="C")
857857
rng2 = bdate_range("12/2/2011", "12/5/2011", freq="C")
858-
rng2.freq = CDay()
858+
rng2._data.freq = CDay() # TODO: shouldnt this already be set?
859859

860860
result = rng1.union(rng2)
861861
assert isinstance(result, DatetimeIndex)

pandas/tests/indexes/datetimes/test_ops.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,12 @@ def test_freq_setter(self, values, freq, tz):
413413
idx = DatetimeIndex(values, tz=tz)
414414

415415
# can set to an offset, converting from string if necessary
416-
idx.freq = freq
416+
idx._data.freq = freq
417417
assert idx.freq == freq
418418
assert isinstance(idx.freq, ABCDateOffset)
419419

420420
# can reset to None
421-
idx.freq = None
421+
idx._data.freq = None
422422
assert idx.freq is None
423423

424424
def test_freq_setter_errors(self):
@@ -431,11 +431,11 @@ def test_freq_setter_errors(self):
431431
"passed frequency 5D"
432432
)
433433
with pytest.raises(ValueError, match=msg):
434-
idx.freq = "5D"
434+
idx._data.freq = "5D"
435435

436436
# setting with non-freq string
437437
with pytest.raises(ValueError, match="Invalid frequency"):
438-
idx.freq = "foo"
438+
idx._data.freq = "foo"
439439

440440
def test_offset_deprecated(self):
441441
# GH 20716

pandas/tests/indexes/datetimes/test_setops.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def test_union_bug_4564(self, sort):
157157
def test_union_freq_both_none(self, sort):
158158
# GH11086
159159
expected = bdate_range("20150101", periods=10)
160-
expected.freq = None
160+
expected._data.freq = None
161161

162162
result = expected.union(expected, sort=sort)
163163
tm.assert_index_equal(result, expected)

pandas/tests/indexes/period/test_ops.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,5 +343,5 @@ def test_freq_setter_deprecated(self):
343343
idx.freq
344344

345345
# warning for setter
346-
with tm.assert_produces_warning(FutureWarning):
346+
with pytest.raises(AttributeError, match="can't set attribute"):
347347
idx.freq = pd.offsets.Day()

pandas/tests/indexes/timedeltas/test_ops.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,12 @@ def test_freq_setter(self, values, freq):
286286
idx = TimedeltaIndex(values)
287287

288288
# can set to an offset, converting from string if necessary
289-
idx.freq = freq
289+
idx._data.freq = freq
290290
assert idx.freq == freq
291291
assert isinstance(idx.freq, ABCDateOffset)
292292

293293
# can reset to None
294-
idx.freq = None
294+
idx._data.freq = None
295295
assert idx.freq is None
296296

297297
def test_freq_setter_errors(self):
@@ -304,13 +304,13 @@ def test_freq_setter_errors(self):
304304
"passed frequency 5D"
305305
)
306306
with pytest.raises(ValueError, match=msg):
307-
idx.freq = "5D"
307+
idx._data.freq = "5D"
308308

309309
# setting with a non-fixed frequency
310310
msg = r"<2 \* BusinessDays> is a non-fixed frequency"
311311
with pytest.raises(ValueError, match=msg):
312-
idx.freq = "2B"
312+
idx._data.freq = "2B"
313313

314314
# setting with non-freq string
315315
with pytest.raises(ValueError, match="Invalid frequency"):
316-
idx.freq = "foo"
316+
idx._data.freq = "foo"

pandas/tests/reshape/test_concat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2774,5 +2774,5 @@ def test_concat_datetimeindex_freq():
27742774
# Non-monotonic index result
27752775
result = pd.concat([expected[50:], expected[:50]])
27762776
expected = pd.DataFrame(data[50:] + data[:50], index=dr[50:].append(dr[:50]))
2777-
expected.index.freq = None
2777+
expected.index._data.freq = None
27782778
tm.assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)