Skip to content

Commit 0797db2

Browse files
committed
DEPR: remove v018 resample compatibilitiy
closes pandas-dev#20554
1 parent 8def649 commit 0797db2

File tree

3 files changed

+12
-276
lines changed

3 files changed

+12
-276
lines changed

doc/source/whatsnew/v0.23.0.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,6 @@ Convert to an xarray DataArray
555555
p.to_xarray()
556556

557557

558-
559558
.. _whatsnew_0230.api_breaking.core_common:
560559

561560
pandas.core.common removals
@@ -923,7 +922,8 @@ Removal of prior version deprecations/changes
923922
- The ``infer_dst`` keyword in :meth:`Series.tz_localize`, :meth:`DatetimeIndex.tz_localize`
924923
and :class:`DatetimeIndex` have been removed. ``infer_dst=True`` is equivalent to
925924
``ambiguous='infer'``, and ``infer_dst=False`` to ``ambiguous='raise'`` (:issue:`7963`).
926-
925+
- When ``.resample()`` was changed from an eager to a lazy operation, like ``.groupby()`` in v0.18.0, we put in place compatibility (with a ``FutureWarning``),
926+
so operations would continue to work. This has now be fully removed (:issue:`20554`)
927927

928928
.. _whatsnew_0230.performance:
929929

pandas/core/resample.py

+10-115
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,6 @@ class Resampler(_GroupBy):
6262
_attributes = ['freq', 'axis', 'closed', 'label', 'convention',
6363
'loffset', 'base', 'kind']
6464

65-
# API compat of allowed attributes
66-
_deprecated_valids = _attributes + ['__doc__', '_cache', '_attributes',
67-
'binner', 'grouper', 'groupby',
68-
'sort', 'kind', 'squeeze', 'keys',
69-
'group_keys', 'as_index', 'exclusions',
70-
'_groupby']
71-
72-
# don't raise deprecation warning on attributes starting with these
73-
# patterns - prevents warnings caused by IPython introspection
74-
_deprecated_valid_patterns = ['_ipython', '_repr']
75-
76-
# API compat of disallowed attributes
77-
_deprecated_invalids = ['iloc', 'loc', 'ix', 'iat', 'at']
78-
7965
def __init__(self, obj, groupby=None, axis=0, kind=None, **kwargs):
8066
self.groupby = groupby
8167
self.keys = None
@@ -100,6 +86,16 @@ def __unicode__(self):
10086
return "{klass} [{attrs}]".format(klass=self.__class__.__name__,
10187
attrs=', '.join(attrs))
10288

89+
def __getattr__(self, attr):
90+
if attr in self._internal_names_set:
91+
return object.__getattribute__(self, attr)
92+
if attr in self._attributes:
93+
return getattr(self.groupby, attr)
94+
if attr in self.obj:
95+
return self[attr]
96+
97+
return object.__getattribute__(self, attr)
98+
10399
@property
104100
def obj(self):
105101
return self.groupby.obj
@@ -124,100 +120,6 @@ def _from_selection(self):
124120
(self.groupby.key is not None or
125121
self.groupby.level is not None))
126122

127-
def _deprecated(self, op):
128-
warnings.warn(("\n.resample() is now a deferred operation\n"
129-
"You called {op}(...) on this deferred object "
130-
"which materialized it into a {klass}\nby implicitly "
131-
"taking the mean. Use .resample(...).mean() "
132-
"instead").format(op=op, klass=self._typ),
133-
FutureWarning, stacklevel=3)
134-
return self.mean()
135-
136-
def _make_deprecated_binop(op):
137-
# op is a string
138-
139-
def _evaluate_numeric_binop(self, other):
140-
result = self._deprecated(op)
141-
return getattr(result, op)(other)
142-
return _evaluate_numeric_binop
143-
144-
def _make_deprecated_unary(op, name):
145-
# op is a callable
146-
147-
def _evaluate_numeric_unary(self):
148-
result = self._deprecated(name)
149-
return op(result)
150-
return _evaluate_numeric_unary
151-
152-
def __array__(self):
153-
return self._deprecated('__array__').__array__()
154-
155-
__gt__ = _make_deprecated_binop('__gt__')
156-
__ge__ = _make_deprecated_binop('__ge__')
157-
__lt__ = _make_deprecated_binop('__lt__')
158-
__le__ = _make_deprecated_binop('__le__')
159-
__eq__ = _make_deprecated_binop('__eq__')
160-
__ne__ = _make_deprecated_binop('__ne__')
161-
162-
__add__ = __radd__ = _make_deprecated_binop('__add__')
163-
__sub__ = __rsub__ = _make_deprecated_binop('__sub__')
164-
__mul__ = __rmul__ = _make_deprecated_binop('__mul__')
165-
__floordiv__ = __rfloordiv__ = _make_deprecated_binop('__floordiv__')
166-
__truediv__ = __rtruediv__ = _make_deprecated_binop('__truediv__')
167-
if not compat.PY3:
168-
__div__ = __rdiv__ = _make_deprecated_binop('__div__')
169-
__neg__ = _make_deprecated_unary(lambda x: -x, '__neg__')
170-
__pos__ = _make_deprecated_unary(lambda x: x, '__pos__')
171-
__abs__ = _make_deprecated_unary(lambda x: np.abs(x), '__abs__')
172-
__inv__ = _make_deprecated_unary(lambda x: -x, '__inv__')
173-
174-
def __getattr__(self, attr):
175-
if attr in self._internal_names_set:
176-
return object.__getattribute__(self, attr)
177-
if attr in self._attributes:
178-
return getattr(self.groupby, attr)
179-
if attr in self.obj:
180-
return self[attr]
181-
182-
if attr in self._deprecated_invalids:
183-
raise ValueError(".resample() is now a deferred operation\n"
184-
"\tuse .resample(...).mean() instead of "
185-
".resample(...)")
186-
187-
matches_pattern = any(attr.startswith(x) for x
188-
in self._deprecated_valid_patterns)
189-
if not matches_pattern and attr not in self._deprecated_valids:
190-
# avoid the warning, if it's just going to be an exception
191-
# anyway.
192-
if not hasattr(self.obj, attr):
193-
raise AttributeError("'{}' has no attribute '{}'".format(
194-
type(self.obj).__name__, attr
195-
))
196-
self = self._deprecated(attr)
197-
198-
return object.__getattribute__(self, attr)
199-
200-
def __setattr__(self, attr, value):
201-
if attr not in self._deprecated_valids:
202-
raise ValueError("cannot set values on {0}".format(
203-
self.__class__.__name__))
204-
object.__setattr__(self, attr, value)
205-
206-
def __getitem__(self, key):
207-
try:
208-
return super(Resampler, self).__getitem__(key)
209-
except (KeyError, AbstractMethodError):
210-
211-
# compat for deprecated
212-
if isinstance(self.obj, ABCSeries):
213-
return self._deprecated('__getitem__')[key]
214-
215-
raise
216-
217-
def __setitem__(self, attr, value):
218-
raise ValueError("cannot set items on {0}".format(
219-
self.__class__.__name__))
220-
221123
def _convert_obj(self, obj):
222124
"""
223125
provide any conversions for the object in order to correctly handle
@@ -282,11 +184,6 @@ def _assure_grouper(self):
282184
def pipe(self, func, *args, **kwargs):
283185
return super(Resampler, self).pipe(func, *args, **kwargs)
284186

285-
def plot(self, *args, **kwargs):
286-
# for compat with prior versions, we want to
287-
# have the warnings shown here and just have this work
288-
return self._deprecated('plot').plot(*args, **kwargs)
289-
290187
_agg_doc = dedent("""
291188
292189
Examples
@@ -853,8 +750,6 @@ def size(self):
853750
return result
854751

855752

856-
Resampler._deprecated_valids += dir(Resampler)
857-
858753

859754
# downsample methods
860755
for method in ['sum', 'prod']:

pandas/tests/test_resample.py

-159
Original file line numberDiff line numberDiff line change
@@ -84,122 +84,6 @@ def test_api(self):
8484
assert isinstance(result, DataFrame)
8585
assert len(result) == 217
8686

87-
def test_api_changes_v018(self):
88-
89-
# change from .resample(....., how=...)
90-
# to .resample(......).how()
91-
92-
r = self.series.resample('H')
93-
assert isinstance(r, DatetimeIndexResampler)
94-
95-
for how in ['sum', 'mean', 'prod', 'min', 'max', 'var', 'std']:
96-
with tm.assert_produces_warning(FutureWarning,
97-
check_stacklevel=False):
98-
result = self.series.resample('H', how=how)
99-
expected = getattr(self.series.resample('H'), how)()
100-
tm.assert_series_equal(result, expected)
101-
102-
with tm.assert_produces_warning(FutureWarning,
103-
check_stacklevel=False):
104-
result = self.series.resample('H', how='ohlc')
105-
expected = self.series.resample('H').ohlc()
106-
tm.assert_frame_equal(result, expected)
107-
108-
# compat for pandas-like methods
109-
for how in ['sort_values', 'isna']:
110-
with tm.assert_produces_warning(FutureWarning,
111-
check_stacklevel=False):
112-
getattr(r, how)()
113-
114-
# invalids as these can be setting operations
115-
r = self.series.resample('H')
116-
pytest.raises(ValueError, lambda: r.iloc[0])
117-
pytest.raises(ValueError, lambda: r.iat[0])
118-
pytest.raises(ValueError, lambda: r.loc[0])
119-
pytest.raises(ValueError, lambda: r.loc[
120-
Timestamp('2013-01-01 00:00:00', offset='H')])
121-
pytest.raises(ValueError, lambda: r.at[
122-
Timestamp('2013-01-01 00:00:00', offset='H')])
123-
124-
def f():
125-
r[0] = 5
126-
127-
pytest.raises(ValueError, f)
128-
129-
# str/repr
130-
r = self.series.resample('H')
131-
with tm.assert_produces_warning(None):
132-
str(r)
133-
with tm.assert_produces_warning(None):
134-
repr(r)
135-
136-
with tm.assert_produces_warning(FutureWarning,
137-
check_stacklevel=False):
138-
tm.assert_numpy_array_equal(np.array(r), np.array(r.mean()))
139-
140-
# masquerade as Series/DataFrame as needed for API compat
141-
assert isinstance(self.series.resample('H'), ABCSeries)
142-
assert not isinstance(self.frame.resample('H'), ABCSeries)
143-
assert not isinstance(self.series.resample('H'), ABCDataFrame)
144-
assert isinstance(self.frame.resample('H'), ABCDataFrame)
145-
146-
# bin numeric ops
147-
for op in ['__add__', '__mul__', '__truediv__', '__div__', '__sub__']:
148-
149-
if getattr(self.series, op, None) is None:
150-
continue
151-
r = self.series.resample('H')
152-
153-
with tm.assert_produces_warning(FutureWarning,
154-
check_stacklevel=False):
155-
assert isinstance(getattr(r, op)(2), Series)
156-
157-
# unary numeric ops
158-
for op in ['__pos__', '__neg__', '__abs__', '__inv__']:
159-
160-
if getattr(self.series, op, None) is None:
161-
continue
162-
r = self.series.resample('H')
163-
164-
with tm.assert_produces_warning(FutureWarning,
165-
check_stacklevel=False):
166-
assert isinstance(getattr(r, op)(), Series)
167-
168-
# comparison ops
169-
for op in ['__lt__', '__le__', '__gt__', '__ge__', '__eq__', '__ne__']:
170-
r = self.series.resample('H')
171-
172-
with tm.assert_produces_warning(FutureWarning,
173-
check_stacklevel=False):
174-
assert isinstance(getattr(r, op)(2), Series)
175-
176-
# IPython introspection shouldn't trigger warning GH 13618
177-
for op in ['_repr_json', '_repr_latex',
178-
'_ipython_canary_method_should_not_exist_']:
179-
r = self.series.resample('H')
180-
with tm.assert_produces_warning(None):
181-
getattr(r, op, None)
182-
183-
# getitem compat
184-
df = self.series.to_frame('foo')
185-
186-
# same as prior versions for DataFrame
187-
pytest.raises(KeyError, lambda: df.resample('H')[0])
188-
189-
# compat for Series
190-
# but we cannot be sure that we need a warning here
191-
with tm.assert_produces_warning(FutureWarning,
192-
check_stacklevel=False):
193-
result = self.series.resample('H')[0]
194-
expected = self.series.resample('H').mean()[0]
195-
assert result == expected
196-
197-
with tm.assert_produces_warning(FutureWarning,
198-
check_stacklevel=False):
199-
result = self.series.resample('H')['2005-01-09 23:00:00']
200-
expected = self.series.resample('H').mean()['2005-01-09 23:00:00']
201-
assert result == expected
202-
20387
def test_groupby_resample_api(self):
20488

20589
# GH 12448
@@ -251,23 +135,6 @@ def test_pipe(self):
251135
result = r.pipe(lambda x: x.max() - x.mean())
252136
tm.assert_frame_equal(result, expected)
253137

254-
@td.skip_if_no_mpl
255-
def test_plot_api(self):
256-
# .resample(....).plot(...)
257-
# hitting warnings
258-
# GH 12448
259-
s = Series(np.random.randn(60),
260-
index=date_range('2016-01-01', periods=60, freq='1min'))
261-
with tm.assert_produces_warning(FutureWarning,
262-
check_stacklevel=False):
263-
result = s.resample('15min').plot()
264-
tm.assert_is_valid_plot_return_object(result)
265-
266-
with tm.assert_produces_warning(FutureWarning,
267-
check_stacklevel=False):
268-
result = s.resample('15min', how='sum').plot()
269-
tm.assert_is_valid_plot_return_object(result)
270-
271138
def test_getitem(self):
272139

273140
r = self.frame.resample('H')
@@ -301,15 +168,6 @@ def test_attribute_access(self):
301168
r = self.frame.resample('H')
302169
tm.assert_series_equal(r.A.sum(), r['A'].sum())
303170

304-
# getting
305-
pytest.raises(AttributeError, lambda: r.F)
306-
307-
# setting
308-
def f():
309-
r.F = 'bah'
310-
311-
pytest.raises(ValueError, f)
312-
313171
def test_api_compat_before_use(self):
314172

315173
# make sure that we are setting the binner
@@ -3012,23 +2870,6 @@ def setup_method(self, method):
30122870
freq='s',
30132871
periods=40))
30142872

3015-
def test_back_compat_v180(self):
3016-
3017-
df = self.frame
3018-
for how in ['sum', 'mean', 'prod', 'min', 'max', 'var', 'std']:
3019-
with tm.assert_produces_warning(FutureWarning,
3020-
check_stacklevel=False):
3021-
result = df.groupby('A').resample('4s', how=how)
3022-
expected = getattr(df.groupby('A').resample('4s'), how)()
3023-
assert_frame_equal(result, expected)
3024-
3025-
with tm.assert_produces_warning(FutureWarning,
3026-
check_stacklevel=False):
3027-
result = df.groupby('A').resample('4s', how='mean',
3028-
fill_method='ffill')
3029-
expected = df.groupby('A').resample('4s').mean().ffill()
3030-
assert_frame_equal(result, expected)
3031-
30322873
def test_tab_complete_ipython6_warning(self, ip):
30332874
from IPython.core.completer import provisionalcompleter
30342875
code = dedent("""\

0 commit comments

Comments
 (0)