Skip to content

Commit

Permalink
DEPR: Remove how, fill_method, and limit from resample (#30139)
Browse files Browse the repository at this point in the history
  • Loading branch information
mroeschke authored and jorisvandenbossche committed Dec 9, 2019
1 parent 17f2ef3 commit 7c278e4
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 104 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
- In :func:`concat` the default value for ``sort`` has been changed from ``None`` to ``False`` (:issue:`20613`)
- Removed previously deprecated "raise_conflict" argument from :meth:`DataFrame.update`, use "errors" instead (:issue:`23585`)
- Removed previously deprecated keyword "n" from :meth:`DatetimeIndex.shift`, :meth:`TimedeltaIndex.shift`, :meth:`PeriodIndex.shift`, use "periods" instead (:issue:`22458`)
- Removed previously deprecated keywords ``how``, ``fill_method``, and ``limit`` from :meth:`DataFrame.resample` (:issue:`30139`)
- Passing an integer to :meth:`Series.fillna` or :meth:`DataFrame.fillna` with ``timedelta64[ns]`` dtype now raises ``TypeError`` (:issue:`24694`)
- Passing multiple axes to :meth:`DataFrame.dropna` is no longer supported (:issue:`20995`)
- Removed previously deprecated :meth:`Series.nonzero`, use `to_numpy().nonzero()` instead (:issue:`24048`)
Expand Down
26 changes: 2 additions & 24 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7728,15 +7728,12 @@ def between_time(
def resample(
self,
rule,
how: Optional[str] = None,
axis=0,
fill_method: Optional[str] = None,
closed: Optional[str] = None,
label: Optional[str] = None,
convention: str = "start",
kind: Optional[str] = None,
loffset=None,
limit: Optional[int] = None,
base: int = 0,
on=None,
level=None,
Expand All @@ -7753,22 +7750,10 @@ def resample(
----------
rule : DateOffset, Timedelta or str
The offset string or object representing target conversion.
how : str
Method for down/re-sampling, default to 'mean' for downsampling.
.. deprecated:: 0.18.0
The new syntax is ``.resample(...).mean()``, or
``.resample(...).apply(<func>)``
axis : {0 or 'index', 1 or 'columns'}, default 0
Which axis to use for up- or down-sampling. For `Series` this
will default to 0, i.e. along the rows. Must be
`DatetimeIndex`, `TimedeltaIndex` or `PeriodIndex`.
fill_method : str, default None
Filling method for upsampling.
.. deprecated:: 0.18.0
The new syntax is ``.resample(...).<func>()``,
e.g. ``.resample(...).pad()``
closed : {'right', 'left'}, default None
Which side of bin interval is closed. The default is 'left'
for all frequency offsets except for 'M', 'A', 'Q', 'BM',
Expand All @@ -7786,10 +7771,6 @@ def resample(
By default the input representation is retained.
loffset : timedelta, default None
Adjust the resampled time labels.
limit : int, default None
Maximum size gap when reindexing with `fill_method`.
.. deprecated:: 0.18.0
base : int, default 0
For frequencies that evenly subdivide 1 day, the "origin" of the
aggregated intervals. For example, for '5min' frequency, base could
Expand Down Expand Up @@ -8021,10 +8002,10 @@ def resample(
2000-01-04 36 90
"""

from pandas.core.resample import resample, _maybe_process_deprecations
from pandas.core.resample import resample

axis = self._get_axis_number(axis)
r = resample(
return resample(
self,
freq=rule,
label=label,
Expand All @@ -8037,9 +8018,6 @@ def resample(
key=on,
level=level,
)
return _maybe_process_deprecations(
r, how=how, fill_method=fill_method, limit=limit
)

def first(self, offset):
"""
Expand Down
56 changes: 1 addition & 55 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from datetime import timedelta
from textwrap import dedent
from typing import Dict, no_type_check
import warnings

import numpy as np

Expand Down Expand Up @@ -953,58 +952,6 @@ def h(self, _method=method):
setattr(Resampler, method, h)


def _maybe_process_deprecations(r, how=None, fill_method=None, limit=None):
"""
Potentially we might have a deprecation warning, show it
but call the appropriate methods anyhow.
"""

if how is not None:

# .resample(..., how='sum')
if isinstance(how, str):
method = "{0}()".format(how)

# .resample(..., how=lambda x: ....)
else:
method = ".apply(<func>)"

# if we have both a how and fill_method, then show
# the following warning
if fill_method is None:
warnings.warn(
"how in .resample() is deprecated\n"
"the new syntax is "
".resample(...).{method}".format(method=method),
FutureWarning,
stacklevel=3,
)
r = r.aggregate(how)

if fill_method is not None:

# show the prior function call
method = "." + method if how is not None else ""

args = "limit={0}".format(limit) if limit is not None else ""
warnings.warn(
"fill_method is deprecated to .resample()\n"
"the new syntax is .resample(...){method}"
".{fill_method}({args})".format(
method=method, fill_method=fill_method, args=args
),
FutureWarning,
stacklevel=3,
)

if how is not None:
r = getattr(r, fill_method)(limit=limit)
else:
r = r.aggregate(fill_method, limit=limit)

return r


class _GroupByMixin(GroupByMixin):
"""
Provide the groupby facilities.
Expand Down Expand Up @@ -1342,8 +1289,7 @@ def get_resampler_for_grouping(

tg = TimeGrouper(freq=rule, **kwargs)
resampler = tg._get_resampler(groupby.obj, kind=kind)
r = resampler._get_resampler_for_grouping(groupby=groupby)
return _maybe_process_deprecations(r, how=how, fill_method=fill_method, limit=limit)
return resampler._get_resampler_for_grouping(groupby=groupby)


class TimeGrouper(Grouper):
Expand Down
29 changes: 11 additions & 18 deletions pandas/tests/resample/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ def test_resample_empty_dtypes(index, dtype, resample_method):


@all_ts
def test_resample_loffset_arg_type(frame, create_index):
@pytest.mark.parametrize("arg", ["mean", {"value": "mean"}, ["mean"]])
def test_resample_loffset_arg_type(frame, create_index, arg):
# GH 13218, 15002
df = frame
expected_means = [df.values[i : i + 2].mean() for i in range(0, len(df.values), 2)]
Expand All @@ -220,26 +221,18 @@ def test_resample_loffset_arg_type(frame, create_index):
expected_index += timedelta(hours=2)
expected = DataFrame({"value": expected_means}, index=expected_index)

for arg in ["mean", {"value": "mean"}, ["mean"]]:
result_agg = df.resample("2D", loffset="2H").agg(arg)

result_agg = df.resample("2D", loffset="2H").agg(arg)
if isinstance(arg, list):
expected.columns = pd.MultiIndex.from_tuples([("value", "mean")])

with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
result_how = df.resample("2D", how=arg, loffset="2H")

if isinstance(arg, list):
expected.columns = pd.MultiIndex.from_tuples([("value", "mean")])

# GH 13022, 7687 - TODO: fix resample w/ TimedeltaIndex
if isinstance(expected.index, TimedeltaIndex):
msg = "DataFrame are different"
with pytest.raises(AssertionError, match=msg):
tm.assert_frame_equal(result_agg, expected)
with pytest.raises(AssertionError, match=msg):
tm.assert_frame_equal(result_how, expected)
else:
# GH 13022, 7687 - TODO: fix resample w/ TimedeltaIndex
if isinstance(expected.index, TimedeltaIndex):
msg = "DataFrame are different"
with pytest.raises(AssertionError, match=msg):
tm.assert_frame_equal(result_agg, expected)
tm.assert_frame_equal(result_how, expected)
else:
tm.assert_frame_equal(result_agg, expected)


@all_ts
Expand Down
3 changes: 0 additions & 3 deletions pandas/tests/resample/test_period_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,12 +732,9 @@ def test_loffset_returns_datetimeindex(self, frame, kind, agg_arg):
expected = DataFrame({"value": expected_means}, index=expected_index)

result_agg = df.resample("2D", loffset="2H", kind=kind).agg(agg_arg)
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
result_how = df.resample("2D", how=agg_arg, loffset="2H", kind=kind)
if isinstance(agg_arg, list):
expected.columns = pd.MultiIndex.from_tuples([("value", "mean")])
tm.assert_frame_equal(result_agg, expected)
tm.assert_frame_equal(result_how, expected)

@pytest.mark.parametrize("freq, period_mult", [("H", 24), ("12H", 2)])
@pytest.mark.parametrize("kind", [None, "period"])
Expand Down
48 changes: 44 additions & 4 deletions pandas/tests/resample/test_resample_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,57 @@ def test_downsample_but_actually_upsampling():

def test_combined_up_downsampling_of_irregular():

# since we are reallydoing an operation like this
# since we are really doing an operation like this
# ts2.resample('2s').mean().ffill()
# preserve these semantics

rng = pd.date_range("1/1/2012", periods=100, freq="S")
ts = Series(np.arange(len(rng)), index=rng)
ts2 = ts.iloc[[0, 1, 2, 3, 5, 7, 11, 15, 16, 25, 30]]

with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
result = ts2.resample("2s", how="mean", fill_method="ffill")
expected = ts2.resample("2s").mean().ffill()
result = ts2.resample("2s").mean().ffill()
expected = Series(
[
0.5,
2.5,
5.0,
7.0,
7.0,
11.0,
11.0,
15.0,
16.0,
16.0,
16.0,
16.0,
25.0,
25.0,
25.0,
30.0,
],
index=pd.DatetimeIndex(
[
"2012-01-01 00:00:00",
"2012-01-01 00:00:02",
"2012-01-01 00:00:04",
"2012-01-01 00:00:06",
"2012-01-01 00:00:08",
"2012-01-01 00:00:10",
"2012-01-01 00:00:12",
"2012-01-01 00:00:14",
"2012-01-01 00:00:16",
"2012-01-01 00:00:18",
"2012-01-01 00:00:20",
"2012-01-01 00:00:22",
"2012-01-01 00:00:24",
"2012-01-01 00:00:26",
"2012-01-01 00:00:28",
"2012-01-01 00:00:30",
],
dtype="datetime64[ns]",
freq="2S",
),
)
tm.assert_series_equal(result, expected)


Expand Down

0 comments on commit 7c278e4

Please sign in to comment.