Skip to content

Commit cd21304

Browse files
committed
DEPR: add deprecation warnings and tests. Update whatsnew
1 parent 7e089aa commit cd21304

File tree

3 files changed

+131
-3
lines changed

3 files changed

+131
-3
lines changed

doc/source/whatsnew/v2.0.0.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ Deprecations
642642
- :meth:`Index.is_object` has been deprecated. Use :func:`pandas.api.types.is_object_dtype` instead (:issue:`50042`)
643643
- :meth:`Index.is_interval` has been deprecated. Use :func:`pandas.api.types.is_intterval_dtype` instead (:issue:`50042`)
644644
- 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`)
645-
-
645+
- Deprecated arguments ``*args`` and ``**kwargs`` in :class:`Resampler` (:issue:`50977`)
646646

647647
.. ---------------------------------------------------------------------------
648648
.. _whatsnew_200.prior_deprecations:
@@ -881,7 +881,6 @@ Removal of prior version deprecations/changes
881881
- Arguments after ``expr`` in :meth:`DataFrame.eval` and :meth:`DataFrame.query` are keyword-only (:issue:`47587`)
882882
- Removed :meth:`Index._get_attributes_dict` (:issue:`50648`)
883883
- Removed :meth:`Series.__array_wrap__` (:issue:`50648`)
884-
- Removed unused ``*args`` and ``**kwargs`` in :class:`Resampler` (:issue:`50977`)
885884

886885
.. ---------------------------------------------------------------------------
887886
.. _whatsnew_200.performance:

pandas/core/resample.py

+89-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
final,
1111
no_type_check,
1212
)
13+
import warnings
1314

1415
import numpy as np
1516

@@ -37,6 +38,7 @@
3738
TimestampConvertibleTypes,
3839
npt,
3940
)
41+
from pandas.compat.numpy import function as nv
4042
from pandas.errors import (
4143
AbstractMethodError,
4244
DataError,
@@ -46,6 +48,7 @@
4648
Substitution,
4749
doc,
4850
)
51+
from pandas.util._exceptions import find_stack_level
4952

5053
from pandas.core.dtypes.generic import (
5154
ABCDataFrame,
@@ -898,54 +901,82 @@ def sum(
898901
self,
899902
numeric_only: bool = False,
900903
min_count: int = 0,
904+
*args,
905+
**kwargs,
901906
):
907+
maybe_warn_args_and_kwargs(type(self), "sum", args, kwargs)
908+
nv.validate_resampler_func("sum", args, kwargs)
902909
return self._downsample("sum", numeric_only=numeric_only, min_count=min_count)
903910

904911
@doc(GroupBy.prod)
905912
def prod(
906913
self,
907914
numeric_only: bool = False,
908915
min_count: int = 0,
916+
*args,
917+
**kwargs,
909918
):
919+
maybe_warn_args_and_kwargs(type(self), "prod", args, kwargs)
920+
nv.validate_resampler_func("prod", args, kwargs)
910921
return self._downsample("prod", numeric_only=numeric_only, min_count=min_count)
911922

912923
def min(
913924
self,
914925
numeric_only: bool = False,
915926
min_count: int = 0,
927+
*args,
928+
**kwargs,
916929
):
930+
maybe_warn_args_and_kwargs(type(self), "min", args, kwargs)
931+
nv.validate_resampler_func("min", args, kwargs)
917932
return self._downsample("min", numeric_only=numeric_only, min_count=min_count)
918933

919934
def max(
920935
self,
921936
numeric_only: bool = False,
922937
min_count: int = 0,
938+
*args,
939+
**kwargs,
923940
):
941+
maybe_warn_args_and_kwargs(type(self), "max", args, kwargs)
942+
nv.validate_resampler_func("max", args, kwargs)
924943
return self._downsample("max", numeric_only=numeric_only, min_count=min_count)
925944

926945
@doc(GroupBy.first)
927946
def first(
928947
self,
929948
numeric_only: bool = False,
930949
min_count: int = 0,
950+
*args,
951+
**kwargs,
931952
):
953+
maybe_warn_args_and_kwargs(type(self), "first", args, kwargs)
954+
nv.validate_resampler_func("first", args, kwargs)
932955
return self._downsample("first", numeric_only=numeric_only, min_count=min_count)
933956

934957
@doc(GroupBy.last)
935958
def last(
936959
self,
937960
numeric_only: bool = False,
938961
min_count: int = 0,
962+
*args,
963+
**kwargs,
939964
):
965+
maybe_warn_args_and_kwargs(type(self), "last", args, kwargs)
966+
nv.validate_resampler_func("last", args, kwargs)
940967
return self._downsample("last", numeric_only=numeric_only, min_count=min_count)
941968

942969
@doc(GroupBy.median)
943-
def median(self, numeric_only: bool = False):
970+
def median(self, numeric_only: bool = False, *args, **kwargs):
971+
maybe_warn_args_and_kwargs(type(self), "median", args, kwargs)
972+
nv.validate_resampler_func("median", args, kwargs)
944973
return self._downsample("median", numeric_only=numeric_only)
945974

946975
def mean(
947976
self,
948977
numeric_only: bool = False,
978+
*args,
979+
**kwargs,
949980
):
950981
"""
951982
Compute mean of groups, excluding missing values.
@@ -964,12 +995,16 @@ def mean(
964995
DataFrame or Series
965996
Mean of values within each group.
966997
"""
998+
maybe_warn_args_and_kwargs(type(self), "mean", args, kwargs)
999+
nv.validate_resampler_func("mean", args, kwargs)
9671000
return self._downsample("mean", numeric_only=numeric_only)
9681001

9691002
def std(
9701003
self,
9711004
ddof: int = 1,
9721005
numeric_only: bool = False,
1006+
*args,
1007+
**kwargs,
9731008
):
9741009
"""
9751010
Compute standard deviation of groups, excluding missing values.
@@ -992,12 +1027,16 @@ def std(
9921027
DataFrame or Series
9931028
Standard deviation of values within each group.
9941029
"""
1030+
maybe_warn_args_and_kwargs(type(self), "std", args, kwargs)
1031+
nv.validate_resampler_func("std", args, kwargs)
9951032
return self._downsample("std", ddof=ddof, numeric_only=numeric_only)
9961033

9971034
def var(
9981035
self,
9991036
ddof: int = 1,
10001037
numeric_only: bool = False,
1038+
*args,
1039+
**kwargs,
10011040
):
10021041
"""
10031042
Compute variance of groups, excluding missing values.
@@ -1021,26 +1060,40 @@ def var(
10211060
DataFrame or Series
10221061
Variance of values within each group.
10231062
"""
1063+
maybe_warn_args_and_kwargs(type(self), "var", args, kwargs)
1064+
nv.validate_resampler_func("var", args, kwargs)
10241065
return self._downsample("var", ddof=ddof, numeric_only=numeric_only)
10251066

10261067
@doc(GroupBy.sem)
10271068
def sem(
10281069
self,
10291070
ddof: int = 1,
10301071
numeric_only: bool = False,
1072+
*args,
1073+
**kwargs,
10311074
):
1075+
maybe_warn_args_and_kwargs(type(self), "sem", args, kwargs)
1076+
nv.validate_resampler_func("sem", args, kwargs)
10321077
return self._downsample("sem", ddof=ddof, numeric_only=numeric_only)
10331078

10341079
@doc(GroupBy.ohlc)
10351080
def ohlc(
10361081
self,
1082+
*args,
1083+
**kwargs,
10371084
):
1085+
maybe_warn_args_and_kwargs(type(self), "ohlc", args, kwargs)
1086+
nv.validate_resampler_func("ohlc", args, kwargs)
10381087
return self._downsample("ohlc")
10391088

10401089
@doc(SeriesGroupBy.nunique)
10411090
def nunique(
10421091
self,
1092+
*args,
1093+
**kwargs,
10431094
):
1095+
maybe_warn_args_and_kwargs(type(self), "nunique", args, kwargs)
1096+
nv.validate_resampler_func("nunique", args, kwargs)
10441097
return self._downsample("nunique")
10451098

10461099
@doc(GroupBy.size)
@@ -2193,3 +2246,38 @@ def _asfreq_compat(index: DatetimeIndex | PeriodIndex | TimedeltaIndex, freq):
21932246
else: # pragma: no cover
21942247
raise TypeError(type(index))
21952248
return new_index
2249+
2250+
2251+
def maybe_warn_args_and_kwargs(cls, kernel: str, args, kwargs) -> None:
2252+
"""
2253+
Warn for deprecation of args and kwargs in resample functions.
2254+
2255+
Parameters
2256+
----------
2257+
cls : type
2258+
Class to warn about.
2259+
kernel : str
2260+
Operation name.
2261+
args : tuple or None
2262+
args passed by user. Will be None if and only if kernel does not have args.
2263+
kwargs : dict or None
2264+
kwargs passed by user. Will be None if and only if kernel does not have kwargs.
2265+
"""
2266+
warn_args = args is not None and len(args) > 0
2267+
warn_kwargs = kwargs is not None and len(kwargs) > 0
2268+
if warn_args and warn_kwargs:
2269+
msg = "args and kwargs"
2270+
elif warn_args:
2271+
msg = "args"
2272+
elif warn_kwargs:
2273+
msg = "kwargs"
2274+
else:
2275+
msg = ""
2276+
if msg != "":
2277+
warnings.warn(
2278+
f"Passing additional {msg} to {cls.__name__}.{kernel} has "
2279+
"no impact on the result and is deprecated. This will "
2280+
"raise a TypeError in a future version of pandas.",
2281+
category=FutureWarning,
2282+
stacklevel=find_stack_level(),
2283+
)

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)