Skip to content

Commit 76025a6

Browse files
authored
DEPR: Remove *args and **kwargs on resample methods (#51042)
1 parent 30cb546 commit 76025a6

File tree

4 files changed

+91
-17
lines changed

4 files changed

+91
-17
lines changed

doc/source/whatsnew/v2.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ Deprecations
780780
- :meth:`Index.is_object` has been deprecated. Use :func:`pandas.api.types.is_object_dtype` instead (:issue:`50042`)
781781
- :meth:`Index.is_interval` has been deprecated. Use :func:`pandas.api.types.is_intterval_dtype` instead (:issue:`50042`)
782782
- Deprecated ``all`` and ``any`` reductions with ``datetime64`` and :class:`DatetimeTZDtype` dtypes, use e.g. ``(obj != pd.Timestamp(0), tz=obj.tz).all()`` instead (:issue:`34479`)
783+
- Deprecated unused arguments ``*args`` and ``**kwargs`` in :class:`Resampler` (:issue:`50977`)
783784
- Deprecated calling ``float`` or ``int`` on a single element :class:`Series` to return a ``float`` or ``int`` respectively. Extract the element before calling ``float`` or ``int`` instead (:issue:`51101`)
784785

785786
.. ---------------------------------------------------------------------------

pandas/core/resample.py

+49
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
final,
1212
no_type_check,
1313
)
14+
import warnings
1415

1516
import numpy as np
1617

@@ -48,6 +49,7 @@
4849
Substitution,
4950
doc,
5051
)
52+
from pandas.util._exceptions import find_stack_level
5153

5254
from pandas.core.dtypes.generic import (
5355
ABCDataFrame,
@@ -893,6 +895,7 @@ def sum(
893895
*args,
894896
**kwargs,
895897
):
898+
maybe_warn_args_and_kwargs(type(self), "sum", args, kwargs)
896899
nv.validate_resampler_func("sum", args, kwargs)
897900
return self._downsample("sum", numeric_only=numeric_only, min_count=min_count)
898901

@@ -904,6 +907,7 @@ def prod(
904907
*args,
905908
**kwargs,
906909
):
910+
maybe_warn_args_and_kwargs(type(self), "prod", args, kwargs)
907911
nv.validate_resampler_func("prod", args, kwargs)
908912
return self._downsample("prod", numeric_only=numeric_only, min_count=min_count)
909913

@@ -914,6 +918,7 @@ def min(
914918
*args,
915919
**kwargs,
916920
):
921+
maybe_warn_args_and_kwargs(type(self), "min", args, kwargs)
917922
nv.validate_resampler_func("min", args, kwargs)
918923
return self._downsample("min", numeric_only=numeric_only, min_count=min_count)
919924

@@ -924,6 +929,7 @@ def max(
924929
*args,
925930
**kwargs,
926931
):
932+
maybe_warn_args_and_kwargs(type(self), "max", args, kwargs)
927933
nv.validate_resampler_func("max", args, kwargs)
928934
return self._downsample("max", numeric_only=numeric_only, min_count=min_count)
929935

@@ -935,6 +941,7 @@ def first(
935941
*args,
936942
**kwargs,
937943
):
944+
maybe_warn_args_and_kwargs(type(self), "first", args, kwargs)
938945
nv.validate_resampler_func("first", args, kwargs)
939946
return self._downsample("first", numeric_only=numeric_only, min_count=min_count)
940947

@@ -946,11 +953,13 @@ def last(
946953
*args,
947954
**kwargs,
948955
):
956+
maybe_warn_args_and_kwargs(type(self), "last", args, kwargs)
949957
nv.validate_resampler_func("last", args, kwargs)
950958
return self._downsample("last", numeric_only=numeric_only, min_count=min_count)
951959

952960
@doc(GroupBy.median)
953961
def median(self, numeric_only: bool = False, *args, **kwargs):
962+
maybe_warn_args_and_kwargs(type(self), "median", args, kwargs)
954963
nv.validate_resampler_func("median", args, kwargs)
955964
return self._downsample("median", numeric_only=numeric_only)
956965

@@ -977,6 +986,7 @@ def mean(
977986
DataFrame or Series
978987
Mean of values within each group.
979988
"""
989+
maybe_warn_args_and_kwargs(type(self), "mean", args, kwargs)
980990
nv.validate_resampler_func("mean", args, kwargs)
981991
return self._downsample("mean", numeric_only=numeric_only)
982992

@@ -1008,6 +1018,7 @@ def std(
10081018
DataFrame or Series
10091019
Standard deviation of values within each group.
10101020
"""
1021+
maybe_warn_args_and_kwargs(type(self), "std", args, kwargs)
10111022
nv.validate_resampler_func("std", args, kwargs)
10121023
return self._downsample("std", ddof=ddof, numeric_only=numeric_only)
10131024

@@ -1040,6 +1051,7 @@ def var(
10401051
DataFrame or Series
10411052
Variance of values within each group.
10421053
"""
1054+
maybe_warn_args_and_kwargs(type(self), "var", args, kwargs)
10431055
nv.validate_resampler_func("var", args, kwargs)
10441056
return self._downsample("var", ddof=ddof, numeric_only=numeric_only)
10451057

@@ -1051,6 +1063,7 @@ def sem(
10511063
*args,
10521064
**kwargs,
10531065
):
1066+
maybe_warn_args_and_kwargs(type(self), "sem", args, kwargs)
10541067
nv.validate_resampler_func("sem", args, kwargs)
10551068
return self._downsample("sem", ddof=ddof, numeric_only=numeric_only)
10561069

@@ -1060,6 +1073,7 @@ def ohlc(
10601073
*args,
10611074
**kwargs,
10621075
):
1076+
maybe_warn_args_and_kwargs(type(self), "ohlc", args, kwargs)
10631077
nv.validate_resampler_func("ohlc", args, kwargs)
10641078
return self._downsample("ohlc")
10651079

@@ -1069,6 +1083,7 @@ def nunique(
10691083
*args,
10701084
**kwargs,
10711085
):
1086+
maybe_warn_args_and_kwargs(type(self), "nunique", args, kwargs)
10721087
nv.validate_resampler_func("nunique", args, kwargs)
10731088
return self._downsample("nunique")
10741089

@@ -2223,3 +2238,37 @@ def _asfreq_compat(index: DatetimeIndex | PeriodIndex | TimedeltaIndex, freq):
22232238
else: # pragma: no cover
22242239
raise TypeError(type(index))
22252240
return new_index
2241+
2242+
2243+
def maybe_warn_args_and_kwargs(cls, kernel: str, args, kwargs) -> None:
2244+
"""
2245+
Warn for deprecation of args and kwargs in resample functions.
2246+
2247+
Parameters
2248+
----------
2249+
cls : type
2250+
Class to warn about.
2251+
kernel : str
2252+
Operation name.
2253+
args : tuple or None
2254+
args passed by user. Will be None if and only if kernel does not have args.
2255+
kwargs : dict or None
2256+
kwargs passed by user. Will be None if and only if kernel does not have kwargs.
2257+
"""
2258+
warn_args = args is not None and len(args) > 0
2259+
warn_kwargs = kwargs is not None and len(kwargs) > 0
2260+
if warn_args and warn_kwargs:
2261+
msg = "args and kwargs"
2262+
elif warn_args:
2263+
msg = "args"
2264+
elif warn_kwargs:
2265+
msg = "kwargs"
2266+
else:
2267+
return
2268+
warnings.warn(
2269+
f"Passing additional {msg} to {cls.__name__}.{kernel} has "
2270+
"no impact on the result and is deprecated. This will "
2271+
"raise a TypeError in a future version of pandas.",
2272+
category=FutureWarning,
2273+
stacklevel=find_stack_level(),
2274+
)

pandas/tests/resample/test_datetime_index.py

-17
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
from pandas._libs import lib
1111
from pandas._typing import DatetimeNaTType
12-
from pandas.errors import UnsupportedFunctionCall
1312

1413
import pandas as pd
1514
from pandas import (
@@ -243,22 +242,6 @@ def _ohlc(group):
243242
tm.assert_frame_equal(result, expected)
244243

245244

246-
@pytest.mark.parametrize("func", ["min", "max", "sum", "prod", "mean", "var", "std"])
247-
def test_numpy_compat(func, unit):
248-
# see gh-12811
249-
s = Series(
250-
[1, 2, 3, 4, 5], index=date_range("20130101", periods=5, freq="s").as_unit(unit)
251-
)
252-
r = s.resample("2s")
253-
254-
msg = "numpy operations are not valid with resample"
255-
256-
with pytest.raises(UnsupportedFunctionCall, match=msg):
257-
getattr(r, func)(func, 1, 2, 3)
258-
with pytest.raises(UnsupportedFunctionCall, match=msg):
259-
getattr(r, func)(axis=1)
260-
261-
262245
def test_resample_how_callables(unit):
263246
# GH#7929
264247
data = np.arange(5, dtype=np.int64)

pandas/tests/resample/test_resample_api.py

+41
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55

66
from pandas._libs import lib
7+
from pandas.errors import UnsupportedFunctionCall
78

89
import pandas as pd
910
from pandas import (
@@ -916,3 +917,43 @@ def test_series_downsample_method(method, numeric_only, expected_data):
916917
result = func(**kwargs)
917918
expected = Series(expected_data, index=expected_index)
918919
tm.assert_series_equal(result, expected)
920+
921+
922+
@pytest.mark.parametrize(
923+
"method, raises",
924+
[
925+
("sum", True),
926+
("prod", True),
927+
("min", True),
928+
("max", True),
929+
("first", False),
930+
("last", False),
931+
("median", False),
932+
("mean", True),
933+
("std", True),
934+
("var", True),
935+
("sem", False),
936+
("ohlc", False),
937+
("nunique", False),
938+
],
939+
)
940+
def test_args_kwargs_depr(method, raises):
941+
index = date_range("20180101", periods=3, freq="h")
942+
df = Series([2, 4, 6], index=index)
943+
resampled = df.resample("30min")
944+
args = ()
945+
946+
func = getattr(resampled, method)
947+
948+
error_msg = "numpy operations are not valid with resample."
949+
error_msg_type = "too many arguments passed in"
950+
warn_msg = f"Passing additional args to DatetimeIndexResampler.{method}"
951+
952+
if raises:
953+
with tm.assert_produces_warning(FutureWarning, match=warn_msg):
954+
with pytest.raises(UnsupportedFunctionCall, match=error_msg):
955+
func(*args, 1, 2, 3)
956+
else:
957+
with tm.assert_produces_warning(FutureWarning, match=warn_msg):
958+
with pytest.raises(TypeError, match=error_msg_type):
959+
func(*args, 1, 2, 3)

0 commit comments

Comments
 (0)