@@ -393,7 +393,7 @@ def transform(self, arg, *args, **kwargs):
393
393
"""
394
394
return self ._selected_obj .groupby (self .groupby ).transform (arg , * args , ** kwargs )
395
395
396
- def _downsample (self , f ):
396
+ def _downsample (self , f , ** kwargs ):
397
397
raise AbstractMethodError (self )
398
398
399
399
def _upsample (self , f , limit = None , fill_value = None ):
@@ -937,25 +937,28 @@ def asfreq(self, fill_value=None):
937
937
"""
938
938
return self ._upsample ("asfreq" , fill_value = fill_value )
939
939
940
- def std (self , ddof = 1 , * args , ** kwargs ):
940
+ def std (self , ddof = 1 , numeric_only : bool = False , * args , ** kwargs ):
941
941
"""
942
942
Compute standard deviation of groups, excluding missing values.
943
943
944
944
Parameters
945
945
----------
946
946
ddof : int, default 1
947
947
Degrees of freedom.
948
+ numeric_only : bool, default False
949
+ Include only `float`, `int` or `boolean` data.
950
+
951
+ .. versionadded:: 1.5.0
948
952
949
953
Returns
950
954
-------
951
955
DataFrame or Series
952
956
Standard deviation of values within each group.
953
957
"""
954
958
nv .validate_resampler_func ("std" , args , kwargs )
955
- # error: Unexpected keyword argument "ddof" for "_downsample"
956
- return self ._downsample ("std" , ddof = ddof ) # type: ignore[call-arg]
959
+ return self ._downsample ("std" , ddof = ddof , numeric_only = numeric_only )
957
960
958
- def var (self , ddof = 1 , * args , ** kwargs ):
961
+ def var (self , ddof = 1 , numeric_only : bool = False , * args , ** kwargs ):
959
962
"""
960
963
Compute variance of groups, excluding missing values.
961
964
@@ -964,14 +967,18 @@ def var(self, ddof=1, *args, **kwargs):
964
967
ddof : int, default 1
965
968
Degrees of freedom.
966
969
970
+ numeric_only : bool, default False
971
+ Include only `float`, `int` or `boolean` data.
972
+
973
+ .. versionadded:: 1.5.0
974
+
967
975
Returns
968
976
-------
969
977
DataFrame or Series
970
978
Variance of values within each group.
971
979
"""
972
980
nv .validate_resampler_func ("var" , args , kwargs )
973
- # error: Unexpected keyword argument "ddof" for "_downsample"
974
- return self ._downsample ("var" , ddof = ddof ) # type: ignore[call-arg]
981
+ return self ._downsample ("var" , ddof = ddof , numeric_only = numeric_only )
975
982
976
983
@doc (GroupBy .size )
977
984
def size (self ):
@@ -1027,53 +1034,94 @@ def quantile(self, q=0.5, **kwargs):
1027
1034
Return a DataFrame, where the coulmns are groupby columns,
1028
1035
and the values are its quantiles.
1029
1036
"""
1030
- # error: Unexpected keyword argument "q" for "_downsample"
1031
- # error: Too many arguments for "_downsample"
1032
- return self ._downsample ("quantile" , q = q , ** kwargs ) # type: ignore[call-arg]
1037
+ return self ._downsample ("quantile" , q = q , ** kwargs )
1033
1038
1034
1039
1035
- # downsample methods
1036
- for method in ["sum" , "prod" , "min" , "max" , "first" , "last" ]:
1040
+ def _add_downsample_kernel (
1041
+ name : str , args : tuple [str , ...], docs_class : type = GroupBy
1042
+ ) -> None :
1043
+ """
1044
+ Add a kernel to Resampler.
1045
+
1046
+ Arguments
1047
+ ---------
1048
+ name : str
1049
+ Name of the kernel.
1050
+ args : tuple
1051
+ Arguments of the method.
1052
+ docs_class : type
1053
+ Class to get kernel docstring from.
1054
+ """
1055
+ assert args in (
1056
+ ("numeric_only" , "min_count" ),
1057
+ ("numeric_only" ,),
1058
+ ("ddof" , "numeric_only" ),
1059
+ (),
1060
+ )
1037
1061
1038
- def f (
1039
- self ,
1040
- _method : str = method ,
1041
- numeric_only : bool | lib .NoDefault = lib .no_default ,
1042
- min_count : int = 0 ,
1043
- * args ,
1044
- ** kwargs ,
1045
- ):
1046
- if numeric_only is lib .no_default :
1047
- if _method != "sum" :
1062
+ # Explicitly provide args rather than args/kwargs for API docs
1063
+ if args == ("numeric_only" , "min_count" ):
1064
+
1065
+ def f (
1066
+ self ,
1067
+ numeric_only : bool | lib .NoDefault = lib .no_default ,
1068
+ min_count : int = 0 ,
1069
+ * args ,
1070
+ ** kwargs ,
1071
+ ):
1072
+ nv .validate_resampler_func (name , args , kwargs )
1073
+ if numeric_only is lib .no_default and name != "sum" :
1048
1074
# For DataFrameGroupBy, set it to be False for methods other than `sum`.
1049
1075
numeric_only = False
1050
1076
1051
- nv .validate_resampler_func (_method , args , kwargs )
1052
- return self ._downsample (_method , numeric_only = numeric_only , min_count = min_count )
1053
-
1054
- f .__doc__ = getattr (GroupBy , method ).__doc__
1055
- setattr (Resampler , method , f )
1056
-
1077
+ return self ._downsample (
1078
+ name , numeric_only = numeric_only , min_count = min_count
1079
+ )
1057
1080
1058
- # downsample methods
1059
- for method in ["mean" , "sem" , "median" , "ohlc" ]:
1081
+ elif args == ("numeric_only" ,):
1082
+ # error: All conditional function variants must have identical signatures
1083
+ def f ( # type: ignore[misc]
1084
+ self , numeric_only : bool | lib .NoDefault = lib .no_default , * args , ** kwargs
1085
+ ):
1086
+ nv .validate_resampler_func (name , args , kwargs )
1087
+ return self ._downsample (name , numeric_only = numeric_only )
1088
+
1089
+ elif args == ("ddof" , "numeric_only" ):
1090
+ # error: All conditional function variants must have identical signatures
1091
+ def f ( # type: ignore[misc]
1092
+ self ,
1093
+ ddof : int = 1 ,
1094
+ numeric_only : bool | lib .NoDefault = lib .no_default ,
1095
+ * args ,
1096
+ ** kwargs ,
1097
+ ):
1098
+ nv .validate_resampler_func (name , args , kwargs )
1099
+ return self ._downsample (name , ddof = ddof , numeric_only = numeric_only )
1060
1100
1061
- def g (self , _method = method , * args , ** kwargs ):
1062
- nv .validate_resampler_func (_method , args , kwargs )
1063
- return self ._downsample (_method )
1101
+ else :
1102
+ # error: All conditional function variants must have identical signatures
1103
+ def f ( # type: ignore[misc]
1104
+ self ,
1105
+ * args ,
1106
+ ** kwargs ,
1107
+ ):
1108
+ nv .validate_resampler_func (name , args , kwargs )
1109
+ return self ._downsample (name )
1064
1110
1065
- g .__doc__ = getattr (GroupBy , method ).__doc__
1066
- setattr (Resampler , method , g )
1111
+ f .__doc__ = getattr (docs_class , name ).__doc__
1112
+ setattr (Resampler , name , f )
1067
1113
1068
1114
1069
- # series only methods
1115
+ for method in ["sum" , "prod" , "min" , "max" , "first" , "last" ]:
1116
+ _add_downsample_kernel (method , ("numeric_only" , "min_count" ))
1117
+ for method in ["mean" , "median" ]:
1118
+ _add_downsample_kernel (method , ("numeric_only" ,))
1119
+ for method in ["sem" ]:
1120
+ _add_downsample_kernel (method , ("ddof" , "numeric_only" ))
1121
+ for method in ["ohlc" ]:
1122
+ _add_downsample_kernel (method , ())
1070
1123
for method in ["nunique" ]:
1071
-
1072
- def h (self , _method = method ):
1073
- return self ._downsample (_method )
1074
-
1075
- h .__doc__ = getattr (SeriesGroupBy , method ).__doc__
1076
- setattr (Resampler , method , h )
1124
+ _add_downsample_kernel (method , (), SeriesGroupBy )
1077
1125
1078
1126
1079
1127
class _GroupByMixin (PandasObject ):
0 commit comments