Skip to content

Commit

Permalink
DEPR: setting DTI.freq, DTI.offset, DTI.asobject (pandas-dev#29801)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and proost committed Dec 19, 2019
1 parent 42538f1 commit 1d827ed
Show file tree
Hide file tree
Showing 14 changed files with 36 additions and 71 deletions.
3 changes: 3 additions & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,9 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
- Removed the previously deprecated :meth:`DataFrame.get_ftype_counts`, :meth:`Series.get_ftype_counts` (:issue:`18243`)
- Removed the previously deprecated :meth:`Index.get_duplicated`, use ``idx[idx.duplicated()].unique()`` instead (:issue:`20239`)
- Removed the previously deprecated :meth:`Series.clip_upper`, :meth:`Series.clip_lower`, :meth:`DataFrame.clip_upper`, :meth:`DataFrame.clip_lower` (:issue:`24203`)
- Removed the ability to alter :attr:`DatetimeIndex.freq`, :attr:`TimedeltaIndex.freq`, or :attr:`PeriodIndex.freq` (:issue:`20772`)
- Removed the previously deprecated :attr:`DatetimeIndex.offset` (:issue:`20730`)
- Removed the previously deprecated :meth:`DatetimeIndex.asobject`, :meth:`TimedeltaIndex.asobject`, :meth:`PeriodIndex.asobject`, use ``astype(object)`` instead (:issue:`29801`)
- Removed previously deprecated "order" argument from :func:`factorize` (:issue:`19751`)
- Removed previously deprecated "v" argument from :meth:`FrozenNDarray.searchsorted`, use "value" instead (:issue:`22672`)
- :func:`read_stata` and :meth:`DataFrame.to_stata` no longer supports the "encoding" argument (:issue:`21400`)
Expand Down
33 changes: 7 additions & 26 deletions pandas/core/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"""
import operator
from typing import Set
import warnings

import numpy as np

Expand Down Expand Up @@ -104,11 +103,6 @@ def freq(self):
"""
return self._data.freq

@freq.setter
def freq(self, value):
# validation is handled by _data setter
self._data.freq = value

@property
def freqstr(self):
"""
Expand Down Expand Up @@ -332,23 +326,6 @@ def take(self, indices, axis=0, allow_fill=True, fill_value=None, **kwargs):
_na_value = NaT
"""The expected NA value to use with this index."""

@property
def asobject(self):
"""
Return object Index which contains boxed values.
.. deprecated:: 0.23.0
Use ``astype(object)`` instead.
*this is an internal non-public method*
"""
warnings.warn(
"'asobject' is deprecated. Use 'astype(object)' instead",
FutureWarning,
stacklevel=2,
)
return self.astype(object)

def _convert_tolerance(self, tolerance, target):
tolerance = np.asarray(to_timedelta(tolerance).to_numpy())

Expand Down Expand Up @@ -612,7 +589,8 @@ def intersection(self, other, sort=False):
result = Index.intersection(self, other, sort=sort)
if isinstance(result, type(self)):
if result.freq is None:
result.freq = to_offset(result.inferred_freq)
# TODO: find a less code-smelly way to set this
result._data._freq = to_offset(result.inferred_freq)
return result

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

# Invalidate the freq of `result`, which may not be correct at
# this point, depending on the values.
result.freq = None

# TODO: find a less code-smelly way to set this
result._data._freq = None
if hasattr(self, "tz"):
result = self._shallow_copy(
result._values, name=result.name, tz=result.tz, freq=None
)
else:
result = self._shallow_copy(result._values, name=result.name, freq=None)
if result.freq is None:
result.freq = to_offset(result.inferred_freq)
# TODO: find a less code-smelly way to set this
result._data._freq = to_offset(result.inferred_freq)
return result

# to make our life easier, "sort" the two ranges
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ def _convert_for_op(self, value):
@Appender(Index.difference.__doc__)
def difference(self, other, sort=None):
new_idx = super().difference(other, sort=sort)
new_idx.freq = None
new_idx._data._freq = None
return new_idx

# --------------------------------------------------------------------
Expand Down Expand Up @@ -522,7 +522,7 @@ def _union(self, other, sort):
if result.freq is None and (
this.freq is not None or other.freq is not None
):
result.freq = to_offset(result.inferred_freq)
result._data._freq = to_offset(result.inferred_freq)
return result

def union_many(self, others):
Expand Down Expand Up @@ -1208,7 +1208,7 @@ def offset(self, value):
)
)
warnings.warn(msg, FutureWarning, stacklevel=2)
self.freq = value
self._data.freq = value

def __getitem__(self, key):
result = self._data.__getitem__(key)
Expand Down
15 changes: 0 additions & 15 deletions pandas/core/indexes/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,21 +313,6 @@ def values(self):
def freq(self) -> DateOffset:
return self._data.freq

@freq.setter
def freq(self, value):
value = Period._maybe_convert_freq(value)
# TODO: When this deprecation is enforced, PeriodIndex.freq can
# be removed entirely, and we'll just inherit.
msg = (
"Setting {cls}.freq has been deprecated and will be "
"removed in a future version; use {cls}.asfreq instead. "
"The {cls}.freq setter is not guaranteed to work."
)
warnings.warn(msg.format(cls=type(self).__name__), FutureWarning, stacklevel=2)
# PeriodArray._freq isn't actually mutable. We set the private _freq
# here, but people shouldn't be doing this anyway.
self._data._freq = value

def _shallow_copy(self, values=None, **kwargs):
# TODO: simplify, figure out type of values
if values is None:
Expand Down
6 changes: 4 additions & 2 deletions pandas/core/indexes/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ def _union(self, other, sort):
result = Index._union(this, other, sort=sort)
if isinstance(result, TimedeltaIndex):
if result.freq is None:
result.freq = to_offset(result.inferred_freq)
# TODO: find a less code-smelly way to set this
result._data._freq = to_offset(result.inferred_freq)
return result

def join(self, other, how="left", level=None, return_indexers=False, sort=False):
Expand Down Expand Up @@ -409,7 +410,8 @@ def intersection(self, other, sort=False):
@Appender(Index.difference.__doc__)
def difference(self, other, sort=None):
new_idx = super().difference(other, sort=sort)
new_idx.freq = None
# TODO: find a less code-smelly way to set this
new_idx._data._freq = None
return new_idx

def _wrap_joined_index(self, joined, other):
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,8 @@ def _downsample(self, how, **kwargs):
if not len(ax):
# reset to the new freq
obj = obj.copy()
obj.index.freq = self.freq
# TODO: find a less code-smelly way to set this
obj.index._data._freq = self.freq
return obj

# do we have a regular frequency
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/arrays/categorical/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def test_constructor_with_datetimelike(self, dtl):
c = Categorical(s)

expected = type(dtl)(s)
expected.freq = None
expected._data.freq = None

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

expected = type(dtl)(s2.dropna())
expected.freq = None
expected._data.freq = None

tm.assert_index_equal(c.categories, expected)

Expand Down
9 changes: 1 addition & 8 deletions pandas/tests/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def test_map_dictlike(self, mapper):

# don't compare the freqs
if isinstance(expected, pd.DatetimeIndex):
expected.freq = None
expected._data.freq = None

result = index.map(mapper(expected, index))
tm.assert_index_equal(result, expected)
Expand All @@ -95,10 +95,3 @@ def test_map_dictlike(self, mapper):
expected = pd.Index([np.nan] * len(index))
result = index.map(mapper([], []))
tm.assert_index_equal(result, expected)

def test_asobject_deprecated(self):
# GH18572
d = self.create_index()
with tm.assert_produces_warning(FutureWarning):
i = d.asobject
assert isinstance(i, pd.Index)
4 changes: 2 additions & 2 deletions pandas/tests/indexes/datetimes/test_date_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ def test_daterange_bug_456(self):
# GH #456
rng1 = bdate_range("12/5/2011", "12/5/2011")
rng2 = bdate_range("12/2/2011", "12/5/2011")
rng2.freq = BDay()
rng2._data.freq = BDay() # TODO: shouldnt this already be set?

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

result = rng1.union(rng2)
assert isinstance(result, DatetimeIndex)
Expand Down
8 changes: 4 additions & 4 deletions pandas/tests/indexes/datetimes/test_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,12 +413,12 @@ def test_freq_setter(self, values, freq, tz):
idx = DatetimeIndex(values, tz=tz)

# can set to an offset, converting from string if necessary
idx.freq = freq
idx._data.freq = freq
assert idx.freq == freq
assert isinstance(idx.freq, ABCDateOffset)

# can reset to None
idx.freq = None
idx._data.freq = None
assert idx.freq is None

def test_freq_setter_errors(self):
Expand All @@ -431,11 +431,11 @@ def test_freq_setter_errors(self):
"passed frequency 5D"
)
with pytest.raises(ValueError, match=msg):
idx.freq = "5D"
idx._data.freq = "5D"

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

def test_offset_deprecated(self):
# GH 20716
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/indexes/datetimes/test_setops.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_union_bug_4564(self, sort):
def test_union_freq_both_none(self, sort):
# GH11086
expected = bdate_range("20150101", periods=10)
expected.freq = None
expected._data.freq = None

result = expected.union(expected, sort=sort)
tm.assert_index_equal(result, expected)
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/indexes/period/test_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,5 +343,5 @@ def test_freq_setter_deprecated(self):
idx.freq

# warning for setter
with tm.assert_produces_warning(FutureWarning):
with pytest.raises(AttributeError, match="can't set attribute"):
idx.freq = pd.offsets.Day()
10 changes: 5 additions & 5 deletions pandas/tests/indexes/timedeltas/test_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ def test_freq_setter(self, values, freq):
idx = TimedeltaIndex(values)

# can set to an offset, converting from string if necessary
idx.freq = freq
idx._data.freq = freq
assert idx.freq == freq
assert isinstance(idx.freq, ABCDateOffset)

# can reset to None
idx.freq = None
idx._data.freq = None
assert idx.freq is None

def test_freq_setter_errors(self):
Expand All @@ -304,13 +304,13 @@ def test_freq_setter_errors(self):
"passed frequency 5D"
)
with pytest.raises(ValueError, match=msg):
idx.freq = "5D"
idx._data.freq = "5D"

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

# setting with non-freq string
with pytest.raises(ValueError, match="Invalid frequency"):
idx.freq = "foo"
idx._data.freq = "foo"
2 changes: 1 addition & 1 deletion pandas/tests/reshape/test_concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2774,5 +2774,5 @@ def test_concat_datetimeindex_freq():
# Non-monotonic index result
result = pd.concat([expected[50:], expected[:50]])
expected = pd.DataFrame(data[50:] + data[:50], index=dr[50:].append(dr[:50]))
expected.index.freq = None
expected.index._data.freq = None
tm.assert_frame_equal(result, expected)

0 comments on commit 1d827ed

Please sign in to comment.